Passing exceptions between two C # programs using JSON

I have a web API that makes HTTP requests to a Windows service that performs certain tasks / commands.

If my β€œservice” throws an exception, I want to pass that exception back to the web API using JSON. Then I want to de-serialize the exception back to the exception object and throw it away.

my code is:

General exception between web API and service:

public class ConnectionErrorException : Exception { public ConnectionErrorException() { } public ConnectionErrorException(String message) : base(message) { } } 

Now in my service I have the following code:

  ... try { result = await ExecuteCommand(userId); //If reached here nothing went wrong, so can return an OK result await p.WriteSuccessAsync(); } catch (Exception e) { //Some thing went wrong. Return the error so they know what the issue is result = e; p.WriteFailure(); } //Write the body of the response: //If the result is null there is no need to send any body, the 200 or 400 header is sufficient if (result != null) { var resultOutput = JsonConvert.SerializeObject(result); await p.OutputStream.WriteAsync(resultOutput); } ... 

So here I am returning a JSON object. Either the response object or the Exception that happened to it.

Then here is the code in the web API that makes the request to the Service:

  // Make request HttpResponseMessage response = await client.PostAsJsonAsync(((int)(command.CommandId)).ToString(), command); if (response.IsSuccessStatusCode) { return await response.Content.ReadAsStringAsync(); } else { var exception = HandleErrorResponse(await response.Content.ReadAsStringAsync()); var type = exception.GetType(); //TODO: try and determine which exact exception it is. throw exception; } 

Now, if the response was successful, I simply return the contents of the string. If the request fails, I try to pass the json response to the exception. However, I have to pass it to the basic exception, as I do - I don’t know what type it is yet. However, when I debug and add a watchdog to the exception. There is a _className parameter that states: "Domain.Model.Exceptions.API.ConnectionErrorException`.

Question: How can I determine which exception was returned and de-serialize it back to the correct exception so that I can throw it again. I need to know the exact type of exception because I handle all the various exceptions, increasing the level of my services in the web API.

Here is a json example that is returned for ConnectionErrorException :

 { "ClassName": "Domain.Model.Exceptions.API.ConnectionErrorException", "Message": null, "Data": null, "InnerException": null, "HelpURL": null, "StackTraceString": "", "HResult": -2146233088, "Source": "LinkProvider.Logic", "WatsonBuckets": null } 
+5
source share
3 answers

Replace exception handling with the following code block.

 else { var response = await response.Content.ReadAsStringAsync(); var exception = JsonConvert.DeserializeObject<Exception>(response); // your handling logic here Console.WriteLine(exception); } 

Therefore, if the service threw a new NotImplementedException("I haz error!") , A System.NotImplementedException: I haz error! will be printed above System.NotImplementedException: I haz error! .


Here is a quick, standalone example using MVVMLight and JSON.net . Say you have sender as

 public class Sender { public Sender() { Messenger.Default.Register<NotificationMessage>(this, message => { if ((Type)message.Target == typeof(Sender)) GotResponse(message.Notification); }); } public void SendRequest(string request) { Console.WriteLine("sending:{0}", request); Messenger.Default.Send( new NotificationMessage(this, typeof(Receiver), request)); } private void GotResponse(string response) { Console.WriteLine("received:{0}", response); if (response.Equals("ok")) return; Exception exception = JsonConvert.DeserializeObject<Exception>(response); Console.WriteLine("exception:{0}", exception); try { throw exception; } catch (Exception e) { Console.WriteLine("Indeed, it was {0}", e); } } } 

and receiver as

 public class Receiver { public Receiver() { Messenger.Default.Register<NotificationMessage>(this, message => { if ((Type)message.Target == typeof(Receiver)) GotRequest(message.Notification); }); } public void SendResponse(string response) { Messenger.Default.Send(new NotificationMessage(this, typeof(Sender), response)); } public void GotRequest(string request) { string response = !string.IsNullOrWhiteSpace(request) ? "ok" : JsonConvert.SerializeObject(new NotImplementedException("I haz error!")); SendResponse(response); } } 

then following "activation"

 var sender = new Sender(); var receiver = new Receiver(); sender.SendRequest("my request"); sender.SendRequest(null); 

will be printed

shipping: my request
received: good

Dispatch:
received: {"ClassName": "System.NotImplementedException", "Message": "...", "WatsonBuckets": null}

Exception: System.NotImplementedException: I was wrong!

Indeed, it was a System.NotImplementedException: I was wrong! in WpfApplication1.View.Sender.GotResponse (line response) in ...

+2
source

You can save the exceptions in a C # dynamic object and then serialize it in JSON and then return it from the Windows service. Again in the web API, you deserialize the JSON and continue the dynamic object. This way you don't have to worry about the actual type of exception. In any case, you can just throw it away. If you want to know the actual type of exception, then you can write code this way where tempData is a dynamic object after deserialization:

 Type exceptionType = ((ObjectHandle)tempData).Unwrap().GetType(); 

And then handle the exception accordingly

Hope this helps :)

+1
source

First of all, in order to be able to deserialize the JSON exception, I had to add an additional constructor to the ConnectionErrorException class:

 public class ConnectionErrorException : Exception { // ... rest of the code protected ConnectionErrorException(SerializationInfo info, StreamingContext context) : base(info, context) { } } 

This is a known issue. For example, see question .

Next, I first read the value of the ClassName property, and then, in accordance with the value, deserialized it to the desired type. I think it would be a good idea to create a helper class for this:

 public static class JsonHelper { public static bool IsInstanceOf<T>(this JsonObject jsonObject) { if (jsonObject == null || !jsonObject.ContainsKey("ClassName")) { return false; } return jsonObject["ClassName"] == typeof(T).FullName; } } 

And then your code might look like this:

 var jsonObject = JsonObject.Parse(json); if(jsonObject.IsInstanceOf<ConnectionErrorException>()) { var connectionErrorException = JsonConvert.DeserializeObject<ConnectionErrorException>(json); } 
+1
source

All Articles