Этот вопрос описывает два подхода к решению сложной архитектурной проблемы, связанной с ASP.NET MVC.К сожалению, наша команда довольно плохо знакома с этой технологией, и мы не нашли надежных источников информации по этой конкретной теме (кроме обзоров, где говорится, что MVC больше относится к разделению, чем к компонентизации).Так что на данный момент мы сомневаемся: подходит ли наше решение или есть другой очевидный способ решения этой проблемы.
У нас есть требование сделать дизайн на основе ASP.NET MVC с учетом компонентизации.Просмотр двигателя Razor также является для нас требованием.Ключевой особенностью здесь является то, что ожидается любой уровень вложенности контроллера (очевидно, через директиву Html.Action
в пределах .cshtml
).Любой контроллер может получить данные через вызов веб-службы (окончательный проект может нарушить это ограничение, как описано ниже).
Проблема заключается в том, что данные должны быть получены асинхронно и максимально параллельно.Например, если два внутренних вызова внутри контроллеров независимы, они должны выполняться параллельно.
На первый взгляд использование асинхронных контроллеров MVC может решить все проблемы.Но есть скрытое предостережение: вложенный контроллер должен быть указан только в cshtml
(в представлении).И представление .cshtml
анализируется после того, как исходный контроллер завершил собственное асинхронное выполнение.Таким образом, все асинхронные операции внутри вложенного контроллера будут выполняться в отдельном асинхронном слоте и, следовательно, не параллельно с первым родительским контроллером.Это ограничение синхронного характера обработки .cshtml
.
После глубокого исследования мы обнаружили, что доступны два варианта.
1) Имеется только один родительский асинхронный контроллер, который будет извлекать все данные и помещать эти данные в контейнер (словарь или любой другой).Вложенные контроллеры не могут выполнять какие-либо внутренние вызовы.Вместо этого у них будет ссылка на инициализированный контейнер с результатами всех внутренних вызовов.Тем не менее, потребитель платформы должен различать родительский и дочерний контроллеры, что не является блестящим решением.
2) Извлечь все данные из бэкэндов в специальный асинхронный HttpModuleЭтот модуль инициализирует тот же контейнер, который будет находиться, например, в HttpContext.Очевидно, что всем контроллерам в таком случае не будет разрешено выполнять какие-либо внутренние вызовы, но они будут иметь унифицированную внутреннюю структуру (по сравнению с опцией # 1).
На данный момент мы считаем, что вариант №2 более желателен, но нас больше интересует надежный, принятый сообществом способ решения этой проблемы в реальных проектах MVC корпоративного уровня.
Буквально любые ссылки / комментарии приветствуются.
[UPD] Требование любого уровня вложенности контроллеров пришло от нашего клиента, которому нужна система, в которой будут представлены полностью повторно используемые компоненты MVC.И они могут быть объединены в любой последовательности с любым уровнем вложенности - как это уже сделано в существующей реализации на основе веб-форм.Это бизнес-правило для существующего приложения, в котором компоненты могут быть объединены в любом случае, поэтому мы не намерены нарушать это правило.На данный момент мы думаем, что такой компонент является комбинацией «контроллер + представление + метаданные», где часть «метаданные» описывает внутренние вызовы, которые должны быть выполнены в сценарии 1 или 2.