我一直在ServiceStack的documentation中冒险从一个返回 Stream 的Action中抛出异常的问题。
问题在于,虽然我服务中的所有其他操作都会返回漂亮的错误,例如:
{
"ResponseStatus": {
"ErrorCode": "ArgumentException",
"Message": "Unable to load data",
"StackTrace": "[GetData: 7/11/2016 1:02:11 PM]:\n[REQUEST: {Token:asdf,Id:1}]\nServiceStack.HttpError: Unable to load codes from token ---> System.ArgumentException: Unable to load codes from token.............(abridged)
}
}
有一个Action的返回类型为Stream,无论返回的异常类型如何,http客户端都会收到以下响应:
使用处理程序(根据SS文档):
Error: ArgumentNullException: As result 'ErrorResponse' is not a supported responseType, a defaultAction must be supplied
Parameter name: defaultAction
没有任何处理程序:
'no content'
400
非常感谢任何帮助。
示例代码 - >
以下是行动的一个例子:
[AddHeader(ContentType = "application/pdf")]
public Stream Get(GetPdfRequest request)
{
throw new NotImplementedException("FAKE EXCEPTION");
}
并在APPHOST的Configure()方法中:
this.UncaughtExceptionHandlers.Add((req, res, operationName, ex) =>
{
var logger = LogManager.GetLogger(GetType());
logger.Error("Unhandled error in API during request binding.", ex);
res.Write("Error: {0}: {1}".Fmt(ex.GetType().Name, ex.Message));
res.EndRequest(skipHeaders: true);
});
this.ServiceExceptionHandlers.Add((httpReq, request, exception) =>
{
var logger = LogManager.GetLogger(GetType());
logger.Error("Unhandled error in API.", exception);
//call default SS exception handler
return DtoUtils.CreateErrorResponse(request, exception);
});
这是我在调用上述Action时在Swagger Rest客户端上看到的内容的屏幕截图。
答案 0 :(得分:4)
The issue is due to being unable to serialize the ErrorResponse
DTO into the unregistered "application/pdf" ContentType.
I've just added a fallback to use the Config.DefaultContentType
for serializing errors in unregistered Content Types in this commit, available from v4.0.61 that's now available on MyGet.
A workaround for prior versions of ServiceStack is instead of using the [AddHeader]
Request Filter Attribute, to instead set the Content-Type in the Service implementation just before you serialize, so any Exceptions are thrown before Response ContentType is set, e.g:
public class ErrorStream {}
public class ErrorStreamService : Service
{
public Stream Any(ErrorStream request)
{
if (!IsValid(request))
throw new NotImplementedException("Exception in Stream Response");
base.Request.ResponseContentType = "application/pdf";
return PdfAsStream(request);
}
}
Which throws a Typed Exception when using a Service Client:
try
{
var response = client.Get<Stream>(new ErrorStream());
Assert.Fail();
}
catch (WebServiceException ex)
{
Assert.That(ex.IsAny400());
Assert.That(!ex.IsAny500());
Assert.That(ex.ErrorCode, Is.EqualTo("NotImplementedException"));
Assert.That(ex.StatusCode, Is.EqualTo((int)HttpStatusCode.MethodNotAllowed));
}
Also UncaughtExceptionHandlers
is only for handling Exceptions thrown outside of a Service, exceptions that occur within a Service are instead handled by ServiceExceptionHandlers
instead, but be careful when modifying the default Exception handling behavior as you can invalidate the typed Exception handling on the client.