Значение CallContext, установленное в фильтре действий веб-API, не передается действию контроллера - PullRequest
0 голосов
/ 04 января 2019

У меня есть веб-API asp.net, где мы начинаем транзакцию, используя TransactionScope (только для POST, PUT и DELETE, но не для GET) в OnActionExecuting фильтра глобальных действий, а затем завершаем или откатываем его обратно в OnActionExecuted.Недавно мы решили внести изменение, чтобы мы могли добавить SqlAzureExecutionStrategy по крайней мере для вызовов GET (поскольку он работает только при отсутствии инициированной пользователем транзакции), чтобы временные сбои могли обрабатываться для выборки данных.Я следовал статье здесь и реализовал то же самое в нашем приложении. Ниже приведен код.

Создан новый класс конфигурации БД

public class AzureDbConfiguration : DbConfiguration
{
    public const string CallContextKey = "SuspendExecutionStrategy";
    public AzureDbConfiguration()
    {
        this.SetExecutionStrategy("System.Data.SqlClient", () => SuspendExecutionStrategy
          ? (IDbExecutionStrategy)new DefaultExecutionStrategy()
          : new SqlAzureExecutionStrategy());   
    }

    public static bool SuspendExecutionStrategy
    {
        get
        {
            return (bool?)CallContext.LogicalGetData(CallContextKey) ?? false;
        }
        set
        {
            CallContext.LogicalSetData(CallContextKey, value);
        }
    }


}

Установка SuspendExecutionStrategy в значение true, когда нам нужно запустить транзакцию.

public override void OnActionExecuting(HttpActionContext actionContext)
    {

        //checks if it is not a GET call
        if (RequiresTransactionInitiation(actionContext))
        {

           AzureDbConfiguration.SuspendExecutionStrategy = true;

            var transactionCompleter = new TransactionCompleter(GetDependencyScope(actionContext));
            transactionCompleter.UnitOfWork.StartTransaction(System.Data.IsolationLevel.ReadCommitted);

        }
        base.OnActionExecuting(actionContext);

    }

    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
        //checks if it is not a GET call
        if (RequiresTransactionCompletion(actionExecutedContext))
        {
            var transactionCompleter = new TransactionCompleter(GetDependencyScope(actionExecutedContext));
            if (actionExecutedContext.Exception == null)
            {

                transactionCompleter.Complete();
                AddEventsToResponseHeader(transactionCompleter.MessageTransactions.OfType<IEventTransaction>(), actionExecutedContext.Response);
            }
            else
            {
                transactionCompleter.Rollback();
            }
        //*********** line is added to just test the value of the property .This always return false.**********
         var testValue = AzureDbConfiguration.SuspendExecutionStrategy;
        }
        base.OnActionExecuted(actionExecutedContext);
    }

Проблема в том, что значение SuspendExecutionStrategy установлено правильно в OnActionExecuting, но в тот момент, когда код вводит действие Controller или OnActionExecuting, оно всегда ложно.

Я провел некоторое исследование и понял, что сам контекст выполнения меняется, когда мы переходим от фильтра к действию контроллера.Поэтому, если в OnActionExecuting я проверяю Thread.CurrentThread.ExecutionContext.ToStringJson (), я вижу, что значение SuspendExecutionStrategy доступно, но если я проверяю то же самое в действии контроллера, оно недоступно, и странная часть - все остальное в контексте выполнения, все еще доступно.

Значение Thread.CurrentThread.ExecutionContext.ToStringJson () в OnActionExecuting

        {
      "LogicalCallContext": {
        "E2ETrace.ActivityID": "80000013-0003-fd00-b63f-84710c7967bb",
        "ApplicationInsights.OwinExtensions.OperationIdContext": "1c218be6-1fbb-44bf-b994-4db84115b5a3",
        "ApplicationInsights.OwinExtensions.OperationParentIdContext": "72d35ac6-a394-4205-8452-a95b36f8857a",
        "SuspendExecutionStrategy" : True
    })

Значение Thread.CurrentThread.ExecutionContext.ToStringJson () вДействие контроллера и OnActionExecuted

{
      "LogicalCallContext": {
        "E2ETrace.ActivityID": "80000013-0003-fd00-b63f-84710c7967bb",
        "ApplicationInsights.OwinExtensions.OperationIdContext": "1c218be6-1fbb-44bf-b994-4db84115b5a3",
        "ApplicationInsights.OwinExtensions.OperationParentIdContext": "72d35ac6-a394-4205-8452-a95b36f8857a",
    })

Поэтому у меня возникает вопрос, как этот контекст выполнения меняется с фильтра действия на действие контроллера и как все остальные значения в контексте выполнения все еще сохраняются.

...