我有一个Web API,它向执行某些任务/命令的Windows服务发出HTTP请求。
如果我的'service'抛出异常,那么我想使用JSON将该异常传递回Web API。然后我想将异常反序列化回异常对象并抛出它。
我的代码:
Web API和服务之间的共享异常:
public class ConnectionErrorException : Exception
{
public ConnectionErrorException()
{
}
public ConnectionErrorException(String message)
: base(message)
{
}
}
现在我的服务中有以下代码:
...
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);
}
...
所以这里我返回一个JSON对象。无论是实际的响应对象,还是碰巧发生的异常。
然后,Web API中的代码向服务发出请求:
// 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;
}
现在,如果响应成功,我只返回字符串内容。如果请求失败,我尝试将json响应传递给异常。但是我必须像往常一样将它传递给基本异常 - 不知道它到底是什么类型。但是当我调试并在异常上添加一个看门狗时。参数_className
表示'Domain.Model.Exceptions.API.ConnectionErrorException`。
问题: 如何确定返回了哪个异常并将其反序列化为正确的异常,以便我可以再次抛出它。我需要知道确切的异常类型,因为我在Web API的服务层中处理了所有不同的异常。
以下是为ConnectionErrorException
:
{
"ClassName": "Domain.Model.Exceptions.API.ConnectionErrorException",
"Message": null,
"Data": null,
"InnerException": null,
"HelpURL": null,
"StackTraceString": "",
"HResult": -2146233088,
"Source": "LinkProvider.Logic",
"WatsonBuckets": null
}
答案 0 :(得分:2)
使用以下代码块替换您的异常处理。
else
{
var response = await response.Content.ReadAsStringAsync();
var exception = JsonConvert.DeserializeObject<Exception>(response);
// your handling logic here
Console.WriteLine(exception);
}
因此,如果服务投放new NotImplementedException("I haz error!")
,则上面会打印出System.NotImplementedException: I haz error!
。
以下是使用MVVMLight
和JSON.net
的快速独立示例。假设你有sender
为
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);
}
}
}
和receiver
为
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);
}
}
然后是“激活”
var sender = new Sender();
var receiver = new Receiver();
sender.SendRequest("my request");
sender.SendRequest(null);
会打印出来
发送:我的请求
收到:OK
发送:
收到:{“ClassName”:“System.NotImplementedException”,“Message”:“...”,“WatsonBuckets”:null}
异常:System.NotImplementedException:我出错了!
确实,它是System.NotImplementedException:我出错!在 WpfApplication1.View.Sender.GotResponse(String response)in ...
答案 1 :(得分:1)
您可以保留C#dynamic
对象的例外,然后将其序列化为JSON,然后从Windows服务返回。再次在Web API上,您将该JSON反序列化并保留为动态对象。通过这种方式,您不必担心实际的异常类型。在任何例外情况下你都可以扔掉它。如果你想知道异常的实际类型,那么你可以写这样的代码,其中tempData
是反序列化后的dynamic
对象:
Type exceptionType = ((ObjectHandle)tempData).Unwrap().GetType();
然后相应地处理异常
希望这会有所帮助:)
答案 2 :(得分:1)
首先能够反序列化异常JSON我被迫向ConnectionErrorException
类添加了一个额外的构造函数:
public class ConnectionErrorException : Exception
{
// ... rest of the code
protected ConnectionErrorException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
}
这是一个已知问题。例如,请检查此question。
接下来,我将首先读取ClassName
属性的值,然后根据该值将其反序列化为所需类型。我认为为此创建一些帮助类是个好主意:
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;
}
}
然后你的代码看起来像那样:
var jsonObject = JsonObject.Parse(json);
if(jsonObject.IsInstanceOf<ConnectionErrorException>())
{
var connectionErrorException =
JsonConvert.DeserializeObject<ConnectionErrorException>(json);
}