This article shows how to implement a post-processor for an ASP.NET MVC application, which transforms the output of an controller action before it is transmitted to the client. The obvious way to do this is by implementing a custom action filter. First, we implement the base filter class:
public abstract class OutputProcessorActionFilterAttribute : ActionFilterAttribute
{
protected abstract string Process(string data);
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
var response = filterContext.HttpContext.Response;
response.Filter = new OutputProcessorStream(response.Filter, Process);
}
}
As you can see in the OnResultExecuted
method, the response’s current Filter
property is wrapped by a new stream implementation. Using this interceptor approach, it is possible to apply multiple action filters to an action method. The actual post-processing of the HTML output is done in the stream implementation OutputProcessorStream
. This stream class gathers all outputs from the wrapped stream, transforms the output and writes the converted HTML data to the client:
internal class OutputProcessorStream : Stream
{
private readonly StringBuilder _data = new StringBuilder();
private readonly Stream _stream;
private readonly Func<string, string> _processor;
public OutputProcessorStream(Stream stream, Func<string, string> processor)
{
_stream = stream;
_processor = processor;
}
public override void Write(byte[] buffer, int offset, int count)
{
_data.Append(Encoding.UTF8.GetString(buffer, offset, count));
}
public override void Close()
{
var output = _outputEncoding.GetBytes(_processor(_data.ToString()));
_stream.Write(output, 0, output.Length);
_stream.Flush();
_data.Clear();
}
...
}
Using the implemented base class, you can implement your specific post-processing action filter. The following class takes the output of an action result and converts all characters to upper case:
public class ToUpperFilterAttribute : OutputProcessorActionFilterAttribute
{
protected override string Process(string data)
{
return data.ToUpper();
}
}
Now, the implemented filter can be applied to your action method:
[ToUpperFilter]
public ActionResult Index()
{
return View();
}
The source code of the final OutputProcessorActionFilterAttribute
class can be found in the MyToolkit library. A sample ASP.NET MVC project can be found on GitHub.
Rico Suter
SOFTWARE ENGINEERING
EDIT
.NET ASP.NET ASP.NET MVC ASP.NET MVC 5 C#