2012-03-29 13 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