Почему порядок регистрации моих ViewEngines кажется несущественным - PullRequest
3 голосов
/ 18 октября 2011

Я написал тест ViewEngine, который отвечает на запросы с именем представления «About», и добавил следующее к методу Application_Start в Global.asax.

ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new RazorViewEngine());
ViewEngines.Engines.Add(new MyViewEngine());

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

if (viewName == "About")
    return new ViewEngineResult(new MyView(), this);
return new ViewEngineResult(new List<string>{"Some arbitrary search location"});

Поскольку контроллер Home отвечает на действие About, я ожидал, что RazorViewEngine обработает запрос на ~/Home/About (как он был добавлен в коллекцию Engines в первую очередь), но это не ... MyViewEngine вместо этого обрабатывает вызовы на этот URL.

Razor правильно обрабатывает вызовы, которые приводят к просмотрам без имени «About».

Даже если я поменяю порядок двух операторов Add выше, я получу точно такое же поведение. Если я закомментирую код, который регистрирует мой механизм просмотра, Razor действительно наберет ~/Home/About, как я и ожидал.

Есть идеи, почему MyViewEngine создает представления впереди Razor, а не должно быть?

1 Ответ

1 голос
/ 22 октября 2011

ASP.NET MVC запрашивает зарегистрированных ViewEngines в порядке их регистрации, как и ожидалось.Однако есть одна загвоздка.Он находится в методе ViewEngineCollection FindView:

public virtual ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName)

Этот метод перебирает доступный ViewEngines, запрашивая представление, но делает это дважды.Один раз с вызовом метода FindView с помощью useCache=true, и если ни один из ViewEngines не дал результата, он повторяет их в другой раз с useCache=false.
Так что в вашем случае, когда он запрашивает RazorViewEngine с useCache=true он не возвращает представление, потому что нет чеченого.Но ваш движок просмотра всегда будет обеспечивать View.Так что вам нужно обработать случай useCache=true в вашей реализации:

public ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
{
    if (useCache)
        return new ViewEngineResult(new List<string> { "Not in cache" });

    if (viewName == "About")
        return new ViewEngineResult(new MyView(), this);
    return new ViewEngineResult(new List<string> { "Some arbitrary search location" });
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...