below is some source code:
public abstract class RazorPageBase : IRazorPage
{
// ...
public dynamic ViewBag => ViewContext.ViewBag;
}
public abstract class Controller : ControllerBase, IActionFilter, IFilterMetadata, IAsyncActionFilter, IDisposable
{
// ...
public dynamic ViewBag
{
get {
if (_viewBag == null)
_viewBag = new DynamicViewData(() => ViewData);
return _viewBag;
}
}
[NonAction]
public virtual ViewResult View(string viewName, object model)
{
ViewData.Model = model;
return new ViewResult()
{
ViewName = viewName,
ViewData = ViewData,
TempData = TempData
};
}
// ...
}
So somehow the ViewBag is passed from the Controller
to the ViewContext
, then I track the source code down to the part that create the ViewContext
and you could check this class: https://source.dot.net/#Microsoft.AspNetCore.Mvc.ViewFeatures/DynamicViewData.cs