Установите код состояния HTTP из IOperationInterceptor в OpenRasta - PullRequest
0 голосов
/ 13 июля 2011

Я написал ExceptionInterceptor, который оборачивает вызов операции в try / catch, чтобы иметь централизованную обработку исключений. То, что я также хочу сделать, это иметь централизованную обработку кода состояния HTTP, но я, кажется, не могу установить код состояния HTTP из моего IOperationInterceptor. Мой перехватчик принимает ICommunicationContext в качестве зависимости и устанавливает для OperationResult, например, OperationResult.BadRequest, но OpenRasta по-прежнему записывает в журнал следующее:

Step into: Stepping over non-user code 'OpenRasta.Pipeline.PipelineRunner.RunCallGraph'
    38-[2011-07-08 09:11:37Z] Start(1) Entering PipelineRunner: Executing contributor OperationResultInvokerContributor.RunOperationResult
        38-[2011-07-08 09:11:37Z] Information(0) Executing OperationResult OperationResult: type=OK, statusCode=200.

Я также пытался установить IResponse.StatusCode явно, но это не имеет никакого эффекта. Похоже, что поскольку ResponseResource, на который я хочу ответить, является допустимым ресурсом, зарегистрированным в ResourceSpace (хотя и без URI), код состояния игнорируется, и обычный конвейер рендеринга продвигается вперед, думая, что «это выглядит хорошо».

Почему OpenRasta игнорирует мой StatusCode?

1 Ответ

1 голос
/ 15 июля 2011

После еще нескольких копаний я понял, что вы не можете переопределить код состояния HTTP напрямую из IOperationInterceptor. Вместо этого вам нужно хранить все данные, которые вам нужны, в коллекции ICommunicationContext.PipelineData, где бы она ни имела смысл в вашей реализации IOperationInterceptor. У меня, например, есть следующая BeforeExecute реализация:

public bool BeforeExecute(IOperation operation)
{
    if (operation.Inputs.Count() > 0)
        this.inputMember = operation.Inputs.First();

    return true;
}

Установка inputMember в BeforeExecute позволяет мне извлекать сущность (полученную через HTTP POST или PUT) через this.inputMember.Binder.BuildObject().Instance, а также получать новый OutputMember в методе RewriteOperation.

Когда вы сохранили все данные, которые вы хотите внутри ICommunicationContext.PipelineData, вы можете перейти к обработке сохраненных данных и соответственно ответить в реализации IPipelineContributor. Вы делаете это, подписавшись на событие After<KnownStages.IOperationExecution>() следующим образом:

public void Initialize(IPipeline pipelineRunner)
{
    pipelineRunner
        .Notify(RenderOnException)
        .After<KnownStages.IOperationExecution>();
}

Метод RenderOnException выглядит следующим образом:

private static PipelineContinuation RenderOnException(ICommunicationContext context)
{
    if (!context.PipelineData.ContainsKey(ExceptionInterceptor.Key))
        return PipelineContinuation.Continue;

    var interestingDataStoredByTheOperationInterceptorImplementation =
        context.PipelineData["SomeKey"];

    // Set context.OperationResult to something meaningful.

    // Instruct the pipeline to render now
    return PipelineContinuation.RenderNow;
}

Хотя это может быть не лучшим способом реализации этого, он работает и в итоге делает тонкими отдельные методы Handler и фокусируется на проблеме, которую они решают. Вместо того, чтобы возвращать OperationResult влево и вправо, методы-обработчики теперь могут генерировать регулярные исключения, которые моя реализация IOperationInterceptor перехватит, а затем моя реализация IPipelineContributor может переопределить OperationResult с соответствующим ответом.

...