Autofac, OrchardProject и AsyncControllers - PullRequest
1 голос
/ 25 июня 2011

Я работаю над тем, чтобы заставить AsyncController работать в OrchardProject.Текущая версия, которую я использую, - 2.2.4.9.0.

У меня было 2 человека, которые следили за моим кодом: http://www.pastie.org/2117952 (AsyncController), который отлично работает в обычном приложении MVC3 vanilla.

По сути, я могу направить в IndexCompleted, но не могу направить в Index.Я собираюсь предположить, что я что-то упускаю в конфигурации Autofac всего проекта.

Я думаю, что конфигурация находится в global.asax: http://pastie.org/2118008

Что я ищу, так это несколько советов, если это правильный способ реализации автозапуска для AsyncControllersили если есть что-то / где-то еще, мне нужно реализовать / инициализировать / и т.д.

~ Dan

Ответы [ 4 ]

2 голосов
/ 06 июля 2011

Orchard, кажется, регистрирует свой собственный IActionInvoker, называемый Orchard.Mvc.Filters.FilterResolvingActionInvoker.

Этот класс является производным от ControllerActionInvoker. Предполагается, что для поддержки асинхронных действий он должен быть производным от AsyncControllerActionInvoker.

Надеюсь, это поможет!

Ник

0 голосов
/ 01 июня 2013

Я также пробовал маршрут AsyncControllerActionInvoker, но безрезультатно.Я получал бы периодически возникающие ошибки от самого Orchard со следующими ошибками:

Orchard.Exceptions.DefaultExceptionPolicy - An unexpected exception was caught
System.TimeoutException: The operation has timed out.
   at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.End()
   at System.Web.Mvc.Async.ReflectedAsyncActionDescriptor.EndExecute(IAsyncResult asyncResult)
   at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass3f.<BeginInvokeAsynchronousActionMethod>b__3e(IAsyncResult asyncResult)
   at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.End()
   at System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult)
   at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass37.<>c__DisplayClass39.<BeginInvokeActionMethodWithFilters>b__33()
   at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass4f.<InvokeActionMethodFilterAsynchronously>b__49()
   at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass4f.<InvokeActionMethodFilterAsynchronously>b__49()
   at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass4f.<InvokeActionMethodFilterAsynchronously>b__49()
NHibernate.Util.ADOExceptionReporter - While preparing SELECT this_.Id as Id236_2_, this_.Number as Number236_2_,...<blah blah blah>
NHibernate.Util.ADOExceptionReporter - The connection object can not be enlisted in transaction scope.

Так что я не думаю, что просто обернуть ваши собственные вызовы базы данных объектом транзакции поможет.Внутренности Орчарда тоже должны быть изменены.

Пойдите, проголосуйте за эту проблему, если хотите, чтобы AsyncControllers поддерживались в Orchard:

https://orchard.codeplex.com/workitem/18012

0 голосов
/ 15 мая 2012

Мне тоже нужно было иметь AsyncController, который я легко изменил FilterResolvingActionInvoker, чтобы он основывался на AsyncControllerActionInvoker вместо ControllerActionInvoker.

Но возникли другие проблемы из-за автоматического удаления транзакции после завершения запроса. В AsyncController начальный поток и поток, который завершает запрос, могут отличаться, что вызывает следующее исключение в методе Dispose класса TransactionManager:

A TransactionScope должен располагаться в том же потоке, в котором он был создан.

Это исключение подавляется без какой-либо регистрации, и его действительно было трудно обнаружить. В этом случае сеанс остается нераспределенным, и последующие сеансы будут остановлены.
Поэтому я сделал метод dispose открытым для ITransactionManager, а теперь в моем AsyncController, когда мне нужен запрос к базе данных, я обертываю его в:

using (_services.TransactionManager) {
    .....
}

новый TransactionManager:

public interface ITransactionManager : IDependency, IDisposable {
    void Demand();
    void Cancel();
}

public class TransactionManager : ITransactionManager {
    private TransactionScope _scope;
    private bool _cancelled;

    public TransactionManager() {
        Logger = NullLogger.Instance;
    }

    public ILogger Logger { get; set; }

    public void Demand() {
        if (_scope == null) {
            Logger.Debug("Creating transaction on Demand");
            _scope = new TransactionScope(
                TransactionScopeOption.Required, 
                new TransactionOptions { 
                    IsolationLevel = IsolationLevel.ReadCommitted 
                });
            _cancelled = false;
        }
    }

    void ITransactionManager.Cancel() {
        Logger.Debug("Transaction cancelled flag set");
        _cancelled = true;
    }

    void IDisposable.Dispose() {
        if (_scope != null) {
            if (!_cancelled) {
                Logger.Debug("Marking transaction as complete");
                _scope.Complete();
            }

            Logger.Debug("Final work for transaction being performed");
            try {
                _scope.Dispose();
            }
            catch {
                // swallowing the exception
            }
            Logger.Debug("Transaction disposed");
        }
        _scope = null;
    }
}

Обратите внимание, что я внес другие небольшие изменения в TransactionManager.

0 голосов
/ 29 июня 2011

Настройка Autofac выглядит нормально, и пока вы можете перейти к что-то Я не могу сказать, что ваше предположение имеет смысл. Кроме того, шаблон, который вы используете для инициализации в global.asax, также используется others .

AsyncController требует, чтобы асинхронные методы были в парах, в вашем случае IndexAsync & IndexCompleted. Вместе они представляют действие Index. Когда вы говорите, что можете перейти к IndexCompleted, вы имеете в виду, что открываете URL ".... / IndexCompleted"?

Кроме того, и это я не могу подтвердить из какой-либо документации, но я бы предположил, что AsyncController требует, чтобы все действия были асинхронными. Таким образом, ваше действие NewMessage вызывает проблемы и должно быть преобразовано в асинхронную NewMessageAsync & NewMessageCompleted пару.

...