ASP.NET последовательность разрешения механизма представления MVC

Я создал простой ASP.NET приложение версии 1.0 MVC. У меня есть ProductController, который имеет один Индекс действия. В представлении я создал соответствующий Index.aspx под подпапкой продукта.

Затем я сослался на Spark dll и создал Index.spark под той же папкой Обзора продукта. Application_Start похож

    protected void Application_Start()
    {
        RegisterRoutes(RouteTable.Routes);

        ViewEngines.Engines.Clear();
        ViewEngines.Engines.Add(new Spark.Web.Mvc.SparkViewFactory());

        ViewEngines.Engines.Add(new WebFormViewEngine());

    }

Мое ожидание состоит в том, что начиная с регистров механизма Spark, прежде чем WebFormViewEngine по умолчанию, когда просматривают Индексное действие в контроллере продукта, механизме Spark, должен использоваться, и WebFormViewEngine должен использоваться для всех других URL.

Однако тест показывает, что Индексное действие для контроллера продукта также использует WebFormViewEngine.

Если я комментирую регистрацию WebFormViewEnginer (последняя строка в коде), я вижу, что Индексное действие представляется механизмом Spark и остальными, URL генерируют ошибку (так как defualt механизма не стало), оказывается, что весь мой код Spark является правильным.

Теперь мой вопрос состоит в том, как механизм представления разрешен? Почему регистрационная последовательность не вступает в силу?

10
задан zero323 17 July 2015 в 23:03
поделиться

2 ответа

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

В случае искры представления должны иметь расширение .spark . WebFormViewEngine ответит на все с расширениями .aspx или .ascx . И, конечно же, как упоминалось выше, вы можете отменить любое из этого, изменив ViewLocationFormats , предоставленный отдельным механизмам просмотра.


Обновлено:

Я просмотрел источник как SparkViewFactory , так и WebFormViewEngine (или, более конкретно, VirtualPathProviderViewEngine , который является производным от ), и я могу сказать вам, почему вы наблюдаете такое странное поведение.

Прежде всего, метод Find в классе ViewEngineCollection работает следующим образом (упрощенно):

foreach (IViewEngine engine in Items) {
    // Query engine for cached view
}

foreach (IViewEngine engine in Items) {
    // Query engine for uncached view
}

Другими словами, он всегда будет пытаться найти кэшированное представление, в любой движок , прежде чем переходить в некэшированный режим.

Способ, которым отдельные механизмы просмотра реализуют это, является второй перегрузкой метода FindView , который принимает аргумент bool с именем useCache .

Однако , и вот где все это становится странным - VirtualPathProviderViewEngine и SparkViewEngine имеют очень разные представления о том, что означает аргумент useCache . Здесь слишком много кода для повторной публикации, но основная идея такова:

  • SparkViewFactory будет искать только в кэше, если useCache имеет значение true . Если ничего не находит, автоматически возвращается «результат промаха кеша», то есть ничего. С другой стороны, если useCache имеет значение false , он вообще не будет смотреть в кеш, он пропустит этап проверки кеша и выполнит обычные действия для разрешения и создания реальный вид.

  • VirtualPathProviderViewEngine , с другой стороны, просматривает кеш, если useCache имеет значение true , и если он не находит представление в кеше , он отключается, создает новый и добавляет его в кеш.

Оба этих подхода работают по отношению к тому, как ViewEngineCollection выполняет поиск.

  • В случае искры он «промахивается» на первой итерации механизмов просмотра, но «попадает» на второй, и после этого представление добавляется в кэш. Без проблем.

  • В случае VirtualPathProviderViewEngine он «пропускает» внутренне, но все равно возвращает «попадание» на первой итерации, после чего представление теперь кэшируется.

Итак, вы должны увидеть, в чем проблема. VirtualPathProviderViewEngine только , похоже, имеет приоритет над SparkViewEngine , потому что первый всегда преуспевает на первой (кэшированной) итерации, но Spark успешно выполняется только на второй (некэшированной) итерации.

Говоря простым языком, Spark действительно сначала спрашивают, но он отвечает: «Нет, у меня еще нет такого представления . Попробуйте вместо этого без кеша». WebForms получает второй вопрос, но автоматически говорит «У меня не было такого мнения, но я все равно пошел и сделал его для вас, вот оно» . И с этого момента WebFormViewEngine всегда получает приоритет, потому что у него кешируется представление, а у Spark нет.


Резюме: Spark получает приоритет, но из-за причуды в том, как Spark обрабатывает аргумент useCache , он теряется, когда движок веб-форм активен в в то же время. Либо WebForm чрезмерно нетерпелив, либо Spark ленив, в зависимости от вашей точки зрения.

Проще говоря, решение состоит в том, чтобы не иметь противоречивых взглядов! Если вы зарегистрировали несколько механизмов просмотра, то вам следует рассматривать любое имя представления, которое может обрабатываться одним / обоими из них, как undefined behavior .

19
ответ дан 3 December 2019 в 19:32
поделиться

Хммм ... Нет, при всем уважении, веб-формы не делают ничего, кроме проверки кеша, когда useCache имеет значение true. То же, что и Spark.

На самом деле - я думаю, что кто-то мог переместить мой сыр ... В Spark могла быть добавлена ​​причуда, вызывающая ложную ошибку кеширования во время прохода useCache == true. Если это правда, то это скорее ошибка, чем другие правила, применяемые к этому параметру.


Обновлено:

Изначально я смотрел на MVC 2 - поэтому я предположил, что выводы @Aaronaught неверны. MVC 2 не возвращает представление на первом проходе, где useCache == true, что отличается в MVC 1.0, который разрешает и заполняет.

Таким образом, разница между способами реализации ASP.NET MVC 1.0 и ASP.NET MVC 2. Spark и MVC 2 одинаково обрабатывают флаг useCache, и порядок их регистрации дает им приоритет.

1
ответ дан 3 December 2019 в 19:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: