2012-03-29 42 views
0

我的情况是这样的:在OpenRasta中,您应该如何处理编解码器错误或异常?

  1. 客户端应用程序执行对抗OpenRasta暴露端点的HTTP POST。
  2. 请求的主体包含导致编解码器出现问题的错误 - 这是OpenRasta.Codecs.IMediaTypeReader的自定义实现。这将JSON负载转换为处理程序期望的POCO。
  3. 编解码器会以有用的方式抛出一个描述错误的异常。例如:Newtonsoft.Json.JsonReaderException: After parsing a value an unexpected character was encountered: ". Line 4, position 5.
  4. 客户端应用程序收到HTTP 405 - MethodNotAllowed。客户端没有看到任何异常细节。

如果编解码器被修改搭上JsonReaderException并返回Missing.Value,类似于Implementing a codec维基,然后客户端会收到一个HTTP 500 - 内部服务器错误。响应的身体还介绍了以下异常:

System.InvalidOperationException: The operation is not ready for invocation. 
    at OpenRasta.OperationModel.MethodBased.MethodBasedOperation.Invoke() 
    at OpenRasta.OperationModel.Interceptors.OperationWithInterceptors.<Invoke>b__0() 
    at OpenRasta.OperationModel.Interceptors.OperationWithInterceptors.Invoke() 
    at OpenRasta.OperationModel.OperationExecutor.Execute(IEnumerable`1 operations) 
    at OpenRasta.Pipeline.Contributors.OperationInvokerContributor.ExecuteOperations(ICommunicationContext context) 
    at OpenRasta.Pipeline.PipelineRunner.ExecuteContributor(ICommunicationContext context, ContributorCall call) 

我应该如何修改我的应用程序,以便:

  • 客户端收到一个HTTP 400错误的请求。
  • 客户端收到一个字符串,其中包含解码器中遇到的异常的详细信息。
+0

在Google Groups上找到这条相关线索:http://groups.google.com/group/openrasta/browse_thread/thread/5deb77ebdc78d79f – Iain 2012-03-29 15:15:16

回答

2

找到this在Google Groups上包含所有答案的线程,我目前的实现看起来像这样。

在我执行的IConfigurationSource

using (OpenRastaConfiguration.Manual) 
{ 
    ResourceSpace.Uses.PipelineContributor<ErrorCheckingContributor>(); 

    // Other configuration here 
} 

然后ErrorCheckingContributor看起来是这样的:

public class ErrorCheckingContributor : IPipelineContributor 
{ 
    public void Initialize(IPipeline pipelineRunner) 
    { 
     pipelineRunner 
      .Notify(CheckRequestDecoding) 
      .After<KnownStages.IOperationResultInvocation>() 
      .And.Before<KnownStages.ICodecResponseSelection>(); 
    } 

    private static PipelineContinuation CheckRequestDecoding(ICommunicationContext context) 
    { 
     if (context.ServerErrors.Count == 0) 
     { 
      return PipelineContinuation.Continue; 
     } 

     var first = context.ServerErrors[0]; 
     if (first.Exception is Newtonsoft.Json.JsonReaderException) 
     { 
      context.Response.Entity.ContentType = MediaType.TextPlain; 
      context.Response.Entity.ContentLength = first.Exception.Message.Length; 
      using (var sw = new StreamWriter(context.Response.Entity.Stream)) 
      { 
       sw.Write(first.Exception.Message); 
      } 
     } 

     return PipelineContinuation.Continue; 
    } 
} 

有一些事情要注意上述:

  • 如果处理程序将抛出一个JsonReaderException,这也将是processe在这里。
  • 它不检查客户端接受哪种媒体类型。这与经历编解码器选择的处理程序抛出的异常不同。
  • 尝试设置context.OperationResultcontext.ServerErrors - 但它不通过编解码器。
3

以上是对上述答案的微小变化 - 这次是根据操作结果数据进行编解码器选择。

IConfigurationSource

using (OpenRastaConfiguration.Manual) 
{ 
    ResourceSpace.Uses.PipelineContributor<ErrorCheckingContributor>(); 

    ResourceSpace.Has.ResourcesOfType<ApplicationError>() 
       .WithoutUri 
       .TranscodedBy<ApplicationErrorCodec>(); 

       // Or use a generic JSON serializer like this: 
       // .AsJsonDataContract(); 

    // Other configuration here 
} 

现在ErrorCheckingContributor看起来是这样的:

public class ErrorCheckingContributor : IPipelineContributor 
{ 
    public void Initialize(IPipeline pipelineRunner) 
    { 
    pipelineRunner 
     .Notify(CheckRequestDecoding) 
     .After<KnownStages.IOperationResultInvocation>() 
     .And.Before<KnownStages.ICodecResponseSelection>(); 
    } 

    private static PipelineContinuation CheckRequestDecoding(ICommunicationContext context) 
    { 
    if (context.ServerErrors.Count == 0) 
    { 
     return PipelineContinuation.Continue; 
    } 

    Error err = context.ServerErrors[0]; 

    // Get a suitable message (err.Message contains stack traces, so try to avoid that) 
    string msg = err.Title; 
    if (msg == null && err.Exception != null) 
     msg = err.Exception.Message; 
    if (msg == null) 
     msg = err.Message; 

    // Create instance of an error information resource which is specific for the application 
    // - This one is rather simple and only contains a copy of the message 
    ApplicationError error = new ApplicationError(msg); 

    // Set operation result to be "400 Bad Request" and remove errors 
    context.OperationResult = new OperationResult.BadRequest { ResponseResource = error }; 
    context.ServerErrors.Clear(); 

    // Render immediately without starting any handlers 
    return PipelineContinuation.RenderNow; 
    } 
} 

ApplicationError是:

public class ApplicationError 
{ 
    public string Message { get; set; } 

    public ApplicationError(string message) 
    { 
    Message = message; 
    } 
} 

最后,我们需要为ApplicationError编解码器ApplicationErrorCodec。这与任何其他IMediaTypeWriter编解码器没有什么不同,但很大程度上取决于您的预期响应媒体类型。一个例子见https://github.com/openrasta/openrasta/wiki/Implementing-a-Codec