This is going to be a horrible linky answer (Sorry moderators its too much code to put in an answer). But Sitecore's habitat example site that does this for assets. In the foundation.assets project, it gets styling and JavaScript from renderings and page content to assemble later on the page. Specifically it is this processor in the mvc.getPageRendering pipeline. It gets the values from a field the rendering and stuffs it into a singleton for later use in the page life cycle. You can just take it one step further and get the field from the datasource of the rendering.
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:set="http://www.sitecore.net/xmlconfig/set/">
<sitecore>
<pipelines>
<mvc.getPageRendering>
<processor patch:before="*[@type='Sitecore.Mvc.Pipelines.Response.GetPageRendering.GetLayoutRendering, Sitecore.Mvc']" type="Sitecore.Foundation.Assets.Pipelines.GetPageRendering.AddRenderingAssets, Sitecore.Foundation.Assets"/>
</mvc.getPageRendering>
</pipelines>
</sitecore>
</configuration>
The moment it reads the field and adds it to the singleton is the line AssetRepository.Current.AddInlineStyling(cssInline, true);
public class AddRenderingAssets : GetPageRenderingProcessor
{
public override void Process(GetPageRenderingArgs args)
{
this.AddAssets(args.PageContext.PageDefinition.Renderings);
}
private void AddAssets(IEnumerable<Rendering> renderings)
{
foreach (var rendering in renderings)
{
var renderingItem = this.GetRenderingItem(rendering);
if (renderingItem == null)
{
return;
}
AddAssetsFromItem(renderingItem);
}
}
protected static void AddAssetsFromItem(Item renderingItem)
{
if (!renderingItem.IsDerived(Templates.RenderingAssets.ID))
return;
AddScriptAssetsFromRendering(renderingItem);
AddInlineScriptFromRendering(renderingItem);
AddStylingAssetsFromRendering(renderingItem);
AddInlineStylingFromAssets(renderingItem);
}
private static void AddInlineStylingFromAssets(Item renderingItem)
{
var cssInline = renderingItem[Templates.RenderingAssets.Fields.InlineStyling];
if (string.IsNullOrEmpty(cssInline))
{
return;
}
var asset = AssetRepository.Current.AddInlineStyling(cssInline, true);
asset.AddOnceToken = renderingItem.ID.ToString();
}
}
https://github.com/Sitecore/Habitat/blob/master/src/Foundation/Assets/code/Pipelines/GetPageRendering/AddPageAssets.cs#L24
The singleton is here. It is marked as [ThreadStatic] so that it is regenerated for each thread request.
https://github.com/Sitecore/Habitat/blob/master/src/Foundation/Assets/code/Repositories/AssetRepository.cs
public class AssetRepository
{
private static readonly AssetRequirementCache _cache = new AssetRequirementCache(StringUtil.ParseSizeString("10MB"));
[ThreadStatic]
private static AssetRepository _current;
private readonly List<Asset> _items = new List<Asset>();
private readonly List<ID> _seenRenderings = new List<ID>();
public static AssetRepository Current => _current ?? (_current = new AssetRepository());
internal IEnumerable<Asset> Items => this._items;
internal void Clear()
{
this._items.Clear();
}
public Asset Add(Asset asset, bool preventAddToCache = false)
{
if (asset == null)
{
throw new ArgumentNullException(nameof(asset));
}
........
}
}
Then in the cshtml file, the contents are read from the singleton and placed on the page. @RenderAssetsService.Current.RenderScript(ScriptLocation.Head)
https://github.com/Sitecore/Habitat/blob/master/src/Project/Habitat/code/Views/Website/Layouts/Default.cshtml#L25
Similar to your request, you can gather all the fields from you datasources for your renderings, add them to a singleton and rendering them on the page.