在 ServiceStack 中访问自定义 ServiceRunner 的 HandleException 中的 responseDTO 类型
Accessing responseDTO type in HandleException of custom ServiceRunner in ServiceStack
我编写了自定义 ServiceRunner 并覆盖了 HandleException 方法。如我所见,如果服务中出现未处理的异常,则由 HandleException 方法编辑的对象 return 将成为服务响应。如果成功,我希望 return 与服务 return 相同的 responseDTO 类型。有什么方法可以访问 HandleException 内部,即遇到异常的服务的 responseDTO 类型?
编辑:
根据收到的答复,我实现了服务(在 F# 中),DTO/service 类型定义如下:
type CS()=
interface IReturn<Op<list<Y>,list<E>>>
member val key = List<int>() with get,set
type CSService() =
interface IService
member this.Get(request: CS)=
//service code here returning Op<list<Y>,seq<E>> type
因此我希望在 HandleException 中收到的类型是 Op<list<Y>,list<E>>
(Y 和 E 是在 bin 文件夹中可用的 dll 中定义的已知类型)
根据建议,我尝试了以下两个选项,因为 WebRequestUtils 在两个命名空间中都可用:
Type test1 = ServiceStack.WebRequestUtils.GetErrorResponseDtoType(request.GetType());//error
Type test2 = ServiceStack.ServiceClient.Web.WebRequestUtils.GetErrorResponseDtoType(request.GetType());
对于 test1,我收到以下异常:
Could not load type 'ServiceStack.ErrorResponse' from assembly 'ServiceStack.Interfaces, Version=3.9.71.0, Culture=neutral, PublicKeyToken=null'.
堆栈跟踪:
at ServiceStack.WebRequestUtils.GetErrorResponseDtoType(Type requestType)
at M.ServiceStackWebAPP.MyCustomServiceRunner`1.HandleException(IRequestContext requestContext, TRequest request, Exception ex) in d:\Projects\ServiceStack\M.WebService\MyCustomServiceRunner.cs:line 167
at ServiceStack.ServiceHost.ServiceRunner`1.Execute(IRequestContext requestContext, Object instance, TRequest request)
at ServiceStack.ServiceHost.ServiceRunner`1.Process(IRequestContext requestContext, Object instance, Object request)
at ServiceStack.ServiceHost.NServiceExec`1.Execute(IRequestContext requestContext, Object instance, Object request, String requestName)
at ServiceStack.ServiceHost.NServiceRequestExec`2.Execute(IRequestContext requestContext, Object instance, Object request)
at ServiceStack.ServiceHost.ServiceController.<>c__DisplayClass15.<>c__DisplayClass17.<RegisterNServiceExecutor>b__14(IRequestContext reqCtx, Object req)
at ServiceStack.ServiceHost.ServiceController.ManagedServiceExec(ServiceExecFn serviceExec, Object service, IRequestContext requestContext, Object dto)
at ServiceStack.ServiceHost.ServiceController.<>c__DisplayClass15.<RegisterNServiceExecutor>b__13(IRequestContext requestContext, Object dto)
at ServiceStack.ServiceHost.ServiceController.Execute(Object request, IRequestContext requestContext)
at ServiceStack.WebHost.Endpoints.EndpointHost.ExecuteService(Object request, EndpointAttributes endpointAttributes, IHttpRequest httpReq, IHttpResponse httpRes)
at ServiceStack.WebHost.Endpoints.Support.EndpointHandlerBase.ExecuteService(Object request, EndpointAttributes endpointAttributes, IHttpRequest httpReq, IHttpResponse httpRes)
at ServiceStack.WebHost.Endpoints.RestHandler.GetResponse(IHttpRequest httpReq, IHttpResponse httpRes, Object request)
at ServiceStack.WebHost.Endpoints.RestHandler.ProcessRequest(IHttpRequest httpReq, IHttpResponse httpRes, String operationName)
测试 2 调用成功,但我收到 ErrorResponse
类型 return 值而不是预期的 Op<list<Y>,list<E>>
.
我是不是还漏掉了什么?
由于 ServiceStack 服务允许您 return 任何响应类型 最终不可能确切地知道如果异常有,服务会 returned不会发生,因为这取决于抛出异常后执行的运行时服务实现逻辑,例如:
public object Any(Request request)
{
throw new Exception(); //No way of knowing what Service would've returned
if (SomeCustomLogic(request))
return new Response1();
return new Response2();
}
尽管如果您按照 ServiceStack 的建议将请求 DTO 标记为 return 类型,例如:
public class MyRequest : IReturn<MyResponse> { ... }
或者 ServiceStack 的约定,响应 DTO 以带有 Response
后缀的请求 DTO 命名,例如:
public class GetCustomers { ... }
public class GetCustomersResponse { ... }
然后您可以使用 WebRequestUtils.GetErrorResponseDtoType(requestType)
从请求 DTO 类型中检索响应类型,例如:
public override object HandleException(IRequest request, T requestDto, Exception ex)
{
var responseType = WebRequestUtils.GetErrorResponseDtoType(requestDto.GetType());
}
如果 ServiceStack 无法推断响应类型(即不使用上面推荐的约定),这将 return 通用 ErrorResponse
类型。
另请注意,您可以使用更有用的 DtoUtils.CreateErrorResponse()
到 return 填充的错误响应 DTO,其中将填充响应 DTO 的 ResponseStatus
属性异常,例如:
public override object HandleException(IRequest request, T requestDto, Exception ex)
{
var errorResponse = DtoUtils.CreateErrorResponse(requestDto, ex);
}
我编写了自定义 ServiceRunner 并覆盖了 HandleException 方法。如我所见,如果服务中出现未处理的异常,则由 HandleException 方法编辑的对象 return 将成为服务响应。如果成功,我希望 return 与服务 return 相同的 responseDTO 类型。有什么方法可以访问 HandleException 内部,即遇到异常的服务的 responseDTO 类型?
编辑: 根据收到的答复,我实现了服务(在 F# 中),DTO/service 类型定义如下:
type CS()=
interface IReturn<Op<list<Y>,list<E>>>
member val key = List<int>() with get,set
type CSService() =
interface IService
member this.Get(request: CS)=
//service code here returning Op<list<Y>,seq<E>> type
因此我希望在 HandleException 中收到的类型是 Op<list<Y>,list<E>>
(Y 和 E 是在 bin 文件夹中可用的 dll 中定义的已知类型)
根据建议,我尝试了以下两个选项,因为 WebRequestUtils 在两个命名空间中都可用:
Type test1 = ServiceStack.WebRequestUtils.GetErrorResponseDtoType(request.GetType());//error
Type test2 = ServiceStack.ServiceClient.Web.WebRequestUtils.GetErrorResponseDtoType(request.GetType());
对于 test1,我收到以下异常:
Could not load type 'ServiceStack.ErrorResponse' from assembly 'ServiceStack.Interfaces, Version=3.9.71.0, Culture=neutral, PublicKeyToken=null'.
堆栈跟踪:
at ServiceStack.WebRequestUtils.GetErrorResponseDtoType(Type requestType)
at M.ServiceStackWebAPP.MyCustomServiceRunner`1.HandleException(IRequestContext requestContext, TRequest request, Exception ex) in d:\Projects\ServiceStack\M.WebService\MyCustomServiceRunner.cs:line 167
at ServiceStack.ServiceHost.ServiceRunner`1.Execute(IRequestContext requestContext, Object instance, TRequest request)
at ServiceStack.ServiceHost.ServiceRunner`1.Process(IRequestContext requestContext, Object instance, Object request)
at ServiceStack.ServiceHost.NServiceExec`1.Execute(IRequestContext requestContext, Object instance, Object request, String requestName)
at ServiceStack.ServiceHost.NServiceRequestExec`2.Execute(IRequestContext requestContext, Object instance, Object request)
at ServiceStack.ServiceHost.ServiceController.<>c__DisplayClass15.<>c__DisplayClass17.<RegisterNServiceExecutor>b__14(IRequestContext reqCtx, Object req)
at ServiceStack.ServiceHost.ServiceController.ManagedServiceExec(ServiceExecFn serviceExec, Object service, IRequestContext requestContext, Object dto)
at ServiceStack.ServiceHost.ServiceController.<>c__DisplayClass15.<RegisterNServiceExecutor>b__13(IRequestContext requestContext, Object dto)
at ServiceStack.ServiceHost.ServiceController.Execute(Object request, IRequestContext requestContext)
at ServiceStack.WebHost.Endpoints.EndpointHost.ExecuteService(Object request, EndpointAttributes endpointAttributes, IHttpRequest httpReq, IHttpResponse httpRes)
at ServiceStack.WebHost.Endpoints.Support.EndpointHandlerBase.ExecuteService(Object request, EndpointAttributes endpointAttributes, IHttpRequest httpReq, IHttpResponse httpRes)
at ServiceStack.WebHost.Endpoints.RestHandler.GetResponse(IHttpRequest httpReq, IHttpResponse httpRes, Object request)
at ServiceStack.WebHost.Endpoints.RestHandler.ProcessRequest(IHttpRequest httpReq, IHttpResponse httpRes, String operationName)
测试 2 调用成功,但我收到 ErrorResponse
类型 return 值而不是预期的 Op<list<Y>,list<E>>
.
我是不是还漏掉了什么?
由于 ServiceStack 服务允许您 return 任何响应类型 最终不可能确切地知道如果异常有,服务会 returned不会发生,因为这取决于抛出异常后执行的运行时服务实现逻辑,例如:
public object Any(Request request)
{
throw new Exception(); //No way of knowing what Service would've returned
if (SomeCustomLogic(request))
return new Response1();
return new Response2();
}
尽管如果您按照 ServiceStack 的建议将请求 DTO 标记为 return 类型,例如:
public class MyRequest : IReturn<MyResponse> { ... }
或者 ServiceStack 的约定,响应 DTO 以带有 Response
后缀的请求 DTO 命名,例如:
public class GetCustomers { ... }
public class GetCustomersResponse { ... }
然后您可以使用 WebRequestUtils.GetErrorResponseDtoType(requestType)
从请求 DTO 类型中检索响应类型,例如:
public override object HandleException(IRequest request, T requestDto, Exception ex)
{
var responseType = WebRequestUtils.GetErrorResponseDtoType(requestDto.GetType());
}
如果 ServiceStack 无法推断响应类型(即不使用上面推荐的约定),这将 return 通用 ErrorResponse
类型。
另请注意,您可以使用更有用的 DtoUtils.CreateErrorResponse()
到 return 填充的错误响应 DTO,其中将填充响应 DTO 的 ResponseStatus
属性异常,例如:
public override object HandleException(IRequest request, T requestDto, Exception ex)
{
var errorResponse = DtoUtils.CreateErrorResponse(requestDto, ex);
}