Maybe the following additional info taken directly from a GitHub MVC issue can answer your question:
Caching includes the Values
dictionary in its lookup. Unless the PopulateValues()
method adds distinct information to ViewLocationExpanderContext.Values
, the ExpandViewLocations()
method will be called just once per original file name i.e. the initial information is cached from then on.
On top of that, the particular example posed by OP can help understand even better, at least that's what happened to me:
- His project has views with the same name under two different directory
trees (say
Foo
and Bar
)
- Depending on some data extracted by current action context, the view to locate should be under either one of those trees
Without any code in PopulateValues()
, view engine will ask once to locate the view, then use view "standard" data (e.g. ControllerName
, ActionName
, Area
, etc.) in order to cache the actual location where view is found.
So, in OP case, once a view location is cached (say e.g. from Foo
directory tree) everytime a view with same name is needed it will always be from that tree, there'll be no way to detect if the one in the other Bar
tree should have been actually picked up.
The only way for OP is to customize PopulateValues()
by adding specific, distinctive view details to Values
dictionary: in current scenario, those are the info extracted from current action context.
That additional info are used two-fold: ExpandViewLocations()
might use them when invoked in order to determine proper location, while view engine will use them to cache view location once found.
Dec. 2021 update
Official doc page is more descriptive. From Remarks section:
Individual IViewLocationExpanders are invoked in two steps:
(1) PopulateValues(ViewLocationExpanderContext)
is invoked and each expander adds values that it would later consume as part of ExpandViewLocations(ViewLocationExpanderContext, IEnumerable<String>)
. The populated values are used to determine a cache key - if all values are identical to the last time PopulateValues(ViewLocationExpanderContext)
was invoked, the cached result is used as the view location.
(2) If no result was found in the cache or if a view was not found at the cached location, ExpandViewLocations(ViewLocationExpanderContext, IEnumerable<String>)
is invoked to determine all potential paths for a view.