orchardcmsorchardcms-1.6

Injecting dynamic content into an Orchard page body


Is it possible to inject dynamic content into an Orchard page body? I would like to inject the id of the current logged in user into links.

My initial thought was to use token replacement, so entering <a href="http://www.someurl.com?id=[memberid]"></a> would replace [memberid] with the logged in user id at runtime. Is there a way I can intercept the response and run some custom code before it is sent back to the client?

This question is the same, however the answer is very specific to their issue.


Solution

  • Tokens might be the proper way to go, however I haven't digged into that yet. But if you want to change the response you can use response filters.

    I used it to minify resulting HTML in this module https://gallery.orchardproject.net/List/Modules/Orchard.Module.JadeX.HtmlMarkupMinifier

    Here's the code that should do the trick or at least give you an idea.

    using System.Globalization;
    using System.IO;
    using System.Text;
    using System.Web.Mvc;
    using Orchard;
    using Orchard.Mvc.Filters;
    using Orchard.UI.Admin;
    
    public class TokenReplacementFilter : FilterProvider, IActionFilter
    {
        private readonly WorkContext _workContext;
    
        public TokenReplacementFilter(IWorkContextAccessor workContextAccessor)
        {
            _workContext = workContextAccessor.GetContext();
        }
    
        public void OnActionExecuting(ActionExecutingContext filterContext) {
            // Only apply the token replacement if logged in and not in the Orchard admin area
            if (filterContext.HttpContext.Response.Filter == null || _workContext.CurrentUser == null || AdminFilter.IsApplied(filterContext.RequestContext))
                return;
    
            filterContext.HttpContext.Response.Filter = new TokenReplacementStream(filterContext.HttpContext.Response.Filter, filterContext.HttpContext.Response.Output.Encoding, _workContext);
        }
    
        public void OnActionExecuted(ActionExecutedContext filterContext)
        {
        }
    }
    
    internal class TokenReplacementStream : MemoryStream
    {
        private readonly Stream _stream;
        private readonly Encoding _encoding;
        private string _html;
        private readonly WorkContext _workContext;
    
        public TokenReplacementStream(Stream filter, Encoding encoding, WorkContext workContext)
        {
            _stream = filter;
            _encoding = encoding;
            _workContext = workContext;
        }
    
        public override void Write(byte[] buffer, int offset, int count)
        {
            _html += _encoding.GetString(buffer);
        }
    
        public override void Flush()
        {
            if (_html != null) {
                _html = _html.Replace("[memberid]", _workContext.CurrentUser.Id.ToString(CultureInfo.InvariantCulture));
                _stream.Write(_encoding.GetBytes(_html), 0, _encoding.GetByteCount(_html));   
            }
        }
    }