【问题标题】:Accessing responseDTO type in HandleException of custom ServiceRunner in ServiceStackServiceStack中自定义ServiceRunner的HandleException中访问responseDTO类型
【发布时间】:2016-10-05 11:03:23
【问题描述】:

我已经编写了自定义 ServiceRunner 并重写了 HandleException 方法。如我所见,如果服务中出现未处理的异常,HandleException 方法返回的对象将成为服务响应。我希望返回与服务在成功的情况下返回的相同的 responseDTO 类型。有什么方法可以在 HandleException 内部访问遇到异常的服务的 responseDTO 类型?

编辑: 根据收到的答案,我使用定义如下的 DTO/服务类型实现了服务(在 F# 中):

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&lt;list&lt;Y&gt;,list&lt;E&gt;&gt; (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)

调用 test2 成功,但我收到 ErrorResponse 类型作为返回值,而不是预期的 Op&lt;list&lt;Y&gt;,list&lt;E&gt;&gt;

我还是错过了什么吗?

【问题讨论】:

    标签: c# exception-handling servicestack-bsd


    【解决方案1】:

    由于 ServiceStack 服务允许您返回任何响应类型,如果没有发生异常,最终不可能确切知道服务将返回什么,因为这将取决于执行的运行时服务实现逻辑抛出异常后,例如:

    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,例如:

    public class MyRequest : IReturn<MyResponse> { ... }
    

    或 ServiceStack 的约定,即使用带有 Response 后缀的请求 DTO 命名响应 DTO,例如:

    public class GetCustomers { ... } 
    public class GetCustomersResponse { ... } 
    

    然后你可以使用WebRequestUtils.GetErrorResponseDtoType(requestType)从Request DTO Type中检索Response Type,例如:

    public override object HandleException(IRequest request, T requestDto, Exception ex)
    {
        var responseType = WebRequestUtils.GetErrorResponseDtoType(requestDto.GetType());
    }
    

    如果 ServiceStack 无法推断响应类型(即不使用上面推荐的约定),这将返回通用的 ErrorResponse 类型。

    还请注意,您可以使用更有用的 DtoUtils.CreateErrorResponse() 返回填充的错误响应 DTO,该响应 DTO 的 ResponseStatus 属性将填充异常,例如:

    public override object HandleException(IRequest request, T requestDto, Exception ex)
    {
        var errorResponse = DtoUtils.CreateErrorResponse(requestDto, ex);
    }
    

    【讨论】:

    • 感谢您的快速回复。我仍然无法接收 responseDTO 类型。我已根据您的回答提供了更多信息。如果需要更多信息,请告诉我。
    • @ronilk 你得到的错误是因为你使用旧 v3 的 ServiceStack 和新的包。所有 ServiceStack 包的版本必须相同,您可以通过查看 NuGet /packages 文件夹来检查。如果您的问题是关于 ServiceStack v3,请标记您的问题 servicestack-bsd 而不是 servicestack
    • 我浏览了 WebRequestUtils.cs 源代码中的 GetErrorResponseDtoType 方法。对我来说,该方法返回 ErrorResponse 而不是 Response 类型,因为 hasResponseStatus 变量变为 false。所以想在这里问一下 ResponseStatus 在除了检查错误细节之外的任何场景中是否重要?如果我没有在任何地方使用 ResponseStatus 那么我可以安全地忽略这部分并直接调用 GetTypeWithGenericTypeDefinitionOf 方法吗?直接在 HandleException 内部调用 GetTypeWithGenericTypeDefinitionOf 对我有用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多