Skip to content
This repository has been archived by the owner on Dec 20, 2019. It is now read-only.

Commit

Permalink
Fixing error handling - local binder.
Browse files Browse the repository at this point in the history
  • Loading branch information
dajuric committed Oct 27, 2017
1 parent 64fd11f commit 441e3e0
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 42 deletions.
12 changes: 7 additions & 5 deletions Samples/Serialization/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class ImageProcessingAPI

Bgr<byte>[,] image = null;
try { image = imgUrl.GetBytes().DecodeAsColorImage(); }
catch { throw new Exception("The specified url does not point to a valid image."); }
catch(Exception ex) { throw new Exception("The specified url does not point to a valid image."); }

image.Apply(c => swapChannels(c, order), inPlace: true);
return image;
Expand All @@ -66,24 +66,26 @@ unsafe Bgr<byte> swapChannels(Bgr<byte> c, int[] order)
var uC = (byte*)Unsafe.AsPointer(ref c);
var swapC = new Bgr<byte>(uC[order[0]], uC[order[1]], uC[order[2]]);
return swapC;
}
}
}

class Program
{
//if access denied execute: "netsh http delete urlacl url=http://+:8001/"
//if access denied execute: "cmd"
//open Index.html to run the client
static void Main(string[] args)
{
Directory.SetCurrentDirectory(Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location));

RPCSettings.MaxMessageSize = 1 * 1024 * 1024; //1MiB
RPCSettings.AddConverter(new JpgBase64Converter());

//generate js code
File.WriteAllText($"../Site/{nameof(ImageProcessingAPI)}.js", RPCJs.GenerateCallerWithDoc<ImageProcessingAPI>());
File.WriteAllText($"../../Site/{nameof(ImageProcessingAPI)}.js", RPCJs.GenerateCallerWithDoc<ImageProcessingAPI>());

//start server and bind its local and remote API
var cts = new CancellationTokenSource();
Server.ListenAsync("http://localhost:8001/", cts.Token, (c, ws) => c.Bind(new ImageProcessingAPI())).Wait(0);
Server.ListenAsync("http://localhost:8001/", cts.Token, (c, ws) => c.Bind(new ImageProcessingAPI())).Wait();

Console.Write("Running: '{0}'. Press [Enter] to exit.", nameof(ServerClientJsSerialization));
Console.ReadLine();
Expand Down
8 changes: 8 additions & 0 deletions Samples/Serialization/Serialization.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@
<OutputType>Exe</OutputType>
<StartupObject />
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<PlatformTarget>AnyCPU</PlatformTarget>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<PlatformTarget>AnyCPU</PlatformTarget>
</PropertyGroup>

<ItemGroup>
<None Remove="Site\LocalAPI.js" />
Expand Down
54 changes: 29 additions & 25 deletions Source/WebSocketRPC.Base/Invokers/LocalInvoker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ static void verifyType(MethodInfo[] methodList)
{
//check constraints
if (typeof(TObj).IsInterface)
throw new Exception("The specified type must be a object type.");
throw new Exception("The specified type must be a class.");

var overloadedMethodNames = methodList.GroupBy(x => x.Name)
.DefaultIfEmpty()
Expand All @@ -71,20 +71,31 @@ static void verifyType(MethodInfo[] methodList)

var propertyList = typeof(TObj).GetProperties(BindingFlags.Public | BindingFlags.Instance);
if (propertyList.Any())
throw new NotSupportedException("The interface must not declare any properties: " + String.Join(", ", propertyList.Select(x => x.Name)) + ".");
throw new NotSupportedException("The class must not declare any properties: " + String.Join(", ", propertyList.Select(x => x.Name)) + ".");
}

public async Task<Response> InvokeAsync(TObj obj, Request clientMessage)
{
var (result, error) = await invokeAsync(obj, clientMessage.FunctionName, clientMessage.Arguments);
JToken result = null;
Exception error = null;

try
{
result = await invokeAsync(obj, clientMessage.FunctionName, clientMessage.Arguments);
}
catch (Exception ex)
{
while (ex.InnerException != null) ex = ex.InnerException;
error = ex;
}

return new Response { FunctionName = clientMessage.FunctionName, ReturnValue = result, Error = error?.Message };
}

async Task<(JToken Result, Exception Error)> invokeAsync(TObj obj, string functionName, JToken[] args)
async Task<JToken> invokeAsync(TObj obj, string functionName, JToken[] args)
{
if (!methods.ContainsKey(functionName))
throw new ArgumentException(functionName + ": The object does not contain the provided method name: " + functionName + ".");
throw new ArgumentException(functionName + ": The object does not contain the provided method name: " + functionName + ".");

var methodParams = methods[functionName].GetParameters();
if (methodParams.Length != args.Length)
Expand All @@ -94,30 +105,23 @@ public async Task<Response> InvokeAsync(TObj obj, Request clientMessage)
for (int i = 0; i < methodParams.Length; i++)
argObjs[i] = args[i].ToObject(methodParams[i].ParameterType, RPCSettings.Serializer);

try

var hasResult = methods[functionName].ReturnType != typeof(void) &&
methods[functionName].ReturnType != typeof(Task);

JToken result = null;
if (hasResult)
{
var hasResult = methods[functionName].ReturnType != typeof(void) &&
methods[functionName].ReturnType != typeof(Task);

JToken result = null;
if (hasResult)
{
var returnVal = await invokeWithResultAsync(methods[functionName], obj, argObjs);
result = (returnVal != null) ? JToken.FromObject(returnVal, RPCSettings.Serializer) : null;
}
else
{
await invokeAsync(methods[functionName], obj, argObjs);
result = JToken.FromObject(true);
}

return (result, null);
var returnVal = await invokeWithResultAsync(methods[functionName], obj, argObjs);
result = (returnVal != null) ? JToken.FromObject(returnVal, RPCSettings.Serializer) : null;
}
catch (Exception ex)
else
{
while (ex.InnerException != null) ex = ex.InnerException;
return (null, ex);
await invokeAsync(methods[functionName], obj, argObjs);
result = JToken.FromObject(true);
}

return result;
}

async Task invokeAsync(MethodInfo method, TObj obj, object[] args)
Expand Down
20 changes: 18 additions & 2 deletions Source/WebsocketRPC.Standalone/ClientServer/Server.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
#endregion

using System;
using System.Collections.Generic;
using System.Net;
using System.Net.WebSockets;
using System.Threading;
Expand All @@ -45,6 +44,23 @@ public static class Server
/// <param name="onConnect">Action executed when connection is created.</param>
/// <returns>Server task.</returns>
public static async Task ListenAsync(string httpListenerPrefix, CancellationToken token, Action<Connection, WebSocketContext> onConnect)
{
await ListenAsync(httpListenerPrefix, token, onConnect, (rq, rp) =>
{
rp.StatusCode = (int)HttpStatusCode.BadRequest;
});
}

/// <summary>
/// Creates and starts a new instance of the http / websocket server.
/// <para>All HTTP requests will have the 'BadRequest' response.</para>
/// </summary>
/// <param name="httpListenerPrefix">The http/https URI listening prefix.</param>
/// <param name="token">Cancellation token.</param>
/// <param name="onConnect">Action executed when connection is created.</param>
/// <param name="onHttpRequest">Action executed on HTTP request.</param>
/// <returns>Server task.</returns>
public static async Task ListenAsync(string httpListenerPrefix, CancellationToken token, Action<Connection, WebSocketContext> onConnect, Action<HttpListenerRequest, HttpListenerResponse> onHttpRequest)
{
var listener = new HttpListener();
listener.Prefixes.Add(httpListenerPrefix);
Expand All @@ -60,7 +76,7 @@ public static async Task ListenAsync(string httpListenerPrefix, CancellationToke
}
else
{
listenerContext.Response.StatusCode = 400;
onHttpRequest(listenerContext.Request, listenerContext.Response);
listenerContext.Response.Close();
}

Expand Down
20 changes: 10 additions & 10 deletions WebsocketRPC.sln
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26730.16
VisualStudioVersion = 15.0.27004.2005
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Source", "Source", "{3CE373E0-6D9A-48C4-808D-510E6FB69D5C}"
EndProject
Expand All @@ -10,29 +10,29 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{E550
Samples\README.md = Samples\README.md
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebsocketRPC.Standalone", "Source\WebsocketRPC.Standalone\WebsocketRPC.Standalone.csproj", "{AB4A5DDF-1F91-4AF8-9E9C-242832576C5E}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebsocketRPC.Standalone", "Source\WebsocketRPC.Standalone\WebsocketRPC.Standalone.csproj", "{AB4A5DDF-1F91-4AF8-9E9C-242832576C5E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebSocketRPC.Js", "Source\WebSocketRPC.JS\WebSocketRPC.Js.csproj", "{965791BF-8F77-4A69-97E2-8B6B66CF9863}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebSocketRPC.Js", "Source\WebSocketRPC.JS\WebSocketRPC.Js.csproj", "{965791BF-8F77-4A69-97E2-8B6B66CF9863}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ServerClientSample", "ServerClientSample", "{E4A64C0A-0127-42AD-A439-2063A145F536}"
ProjectSection(SolutionItems) = preProject
Samples\ServerClientSample\Run.bat = Samples\ServerClientSample\Run.bat
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServerClientJs", "Samples\ClientJs\ServerClientJs.csproj", "{C0449FA5-C667-4B5C-878A-04773903B130}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ServerClientJs", "Samples\ClientJs\ServerClientJs.csproj", "{C0449FA5-C667-4B5C-878A-04773903B130}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Client", "Samples\ServerClientSample\Client\Client.csproj", "{E0DBB446-3B2B-4BC2-871F-925AB60917E3}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Client", "Samples\ServerClientSample\Client\Client.csproj", "{E0DBB446-3B2B-4BC2-871F-925AB60917E3}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Server", "Samples\ServerClientSample\Server\Server.csproj", "{841054C8-559B-4E6F-8DCD-44C2D3DA2F0B}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Server", "Samples\ServerClientSample\Server\Server.csproj", "{841054C8-559B-4E6F-8DCD-44C2D3DA2F0B}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{26CCD24E-8415-4FD5-8AB3-17433A265B08}"
ProjectSection(SolutionItems) = preProject
.nuget\NuGet.exe = .nuget\NuGet.exe
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MultiService", "Samples\MultiService\MultiService.csproj", "{2B69F62E-991C-4E4B-B1FF-2A5906415764}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MultiService", "Samples\MultiService\MultiService.csproj", "{2B69F62E-991C-4E4B-B1FF-2A5906415764}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Serialization", "Samples\Serialization\Serialization.csproj", "{9F82F6DD-238B-4F65-A95C-55F2BA20F1B0}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Serialization", "Samples\Serialization\Serialization.csproj", "{9F82F6DD-238B-4F65-A95C-55F2BA20F1B0}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{6B3680DB-211E-492C-BC67-46FF1F00A730}"
ProjectSection(SolutionItems) = preProject
Expand All @@ -55,9 +55,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "NuGet", "NuGet", "{CBCEF1A5
EndProject
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "WebSocketRPC.Base", "Source\WebSocketRPC.Base\WebSocketRPC.Base.shproj", "{EAEBAA06-D5BB-4106-8694-C022832175D6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebSocketRPC.AspCore", "Source\WebSocketRPC.AspCore\WebSocketRPC.AspCore.csproj", "{CE4BAD88-2358-4B3D-8A34-90A74C73E521}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebSocketRPC.AspCore", "Source\WebSocketRPC.AspCore\WebSocketRPC.AspCore.csproj", "{CE4BAD88-2358-4B3D-8A34-90A74C73E521}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AspRpc", "Samples\AspRpc\AspRpc.csproj", "{CFC334A5-2B52-42A0-87AE-4B3F84B09530}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AspRpc", "Samples\AspRpc\AspRpc.csproj", "{CFC334A5-2B52-42A0-87AE-4B3F84B09530}"
EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
Expand Down

0 comments on commit 441e3e0

Please sign in to comment.