January 2018 : Instructor-led Online Course in ASP.NET Core 2.0. Conducted by Bipin Joshi. Read more...
Registration for January 2018 batch of ASP.NET Core 2.0 instructor-led online course has already started. Conducted by Bipin Joshi. Register today ! Click here for more details.

Modify Response Content in ASP.NET MVC using a Custom Action Filter

Recently I came across a requirement wherein I wanted to modify the response content being generated from an ASP.NET MVC view. What I wanted to accomplish was this - read the HTML content that is being sent to the browser and highlight certain words from the content. This article explains how this can be accomplished.

Let's assume that you have a view that displays list of employees from the Employees table of Northwind database.

Suppose that you have a separate database table that lists certain keywords. You need to intercept response content of each view and highlight those keywords. In the above figure USA is such a keyword. The logic to do this highlighting can't be included in individual controller or view for the sake of avoiding duplication. Moreover, doing so would mix two separate operations - displaying data and highlighting keywords - causing design issues. A real world example of this nature is advertising engines that intercept HTML content of a page and then insert hyperlinks around certain keywords. Obviously the page and the advertisements are separate concerns altogether and should be kept separate. Luckily, ASP.NET MVC allows you to create custom action filters that can do the job.

Let's create a custom action filter that will read the response stream and then search the content for USA keyword and then highlight it as needed. We will call our custom action filter - KeywordFilter. The following code shows how the filter will be used:

[KeywordFilter]
public ActionResult Index()
{
    NorthwindEntities db = new NorthwindEntities();
    return View(db.Employees.ToList());
}

Ok. First of all add a new class to the ASP.NET MVC project as shown below:

public class KeywordStream : MemoryStream
{
    private readonly Stream responseStream;

    public KeywordStream(Stream stream)
    {
        responseStream = stream;
    }

    public override void Write(byte[] buffer, 
    int offset, int count)
    {
        string html = Encoding.UTF8.GetString(buffer);
        html = html.Replace("USA", 
               "<span class='keyword'>USA</span>");            
        buffer = Encoding.UTF8.GetBytes(html);
        responseStream.Write(buffer, offset, buffer.Length);
    }

}

The KeywordStream class inherits from MemoryStream class. The constructor accepts a Stream object and stores in a private variable responseStream. The class then overrides Write() method. This is the place where the keyword highlighting happens. Inside, we read the contents of the stream and replace USA with highlighted HTML fragment. In the above code I simply wrap the keyword inside a <span> element but you can add anything of your choice here (such as a hyperlink). Note that for the sake of simplicity I use Write() to do this job. If your response content is quite large you may think of overriding Flush() or Close() instead of Write().

Now add KeywordFilterAttribute class and modify it as shown below:

public class KeywordFilterAttribute:ActionFilterAttribute
{

    public override void OnActionExecuting
    (ActionExecutingContext filterContext)
    {
        var originalFilter = 
            filterContext.HttpContext.Response.Filter;
        filterContext.HttpContext.Response.Filter = 
        new KeywordStream(originalFilter);
    }

}

The KeywordFilterAttribute class inherits from ActionFilterAttribute class. It then overrides OnActionExecuting() methods of the base class. Inside, we grab the Response.Filter property (which is basically a stream) and store it in a private variable. We then replace the Filter property with our newly created stream - KeywordStream - and pass the original filter stream to its constructor.

The following markup shows how the Index view looks like:

@model List<KeywordHighlightDemo.Models.Employee>

...
    <style>
        .keyword
        {
            background-color:yellow;
            color:red;
            font-weight:bold;
            padding:2px;
        }
    </style>
...
    <h1>List of Employees</h1>
    <table border="1" cellpadding="10">
        @foreach(var item in Model)
        {
            <tr>
                <td>@item.EmployeeID</td>
                <td>@item.FirstName</td>
                <td>@item.LastName</td>
                <td>@item.Country</td>
            </tr>
        }
    </table>
...

As you can see, we simply run a foreach loop and output the Employee data in a table.

That's it! Run the application and see if the USA keyword is getting highlighted.


Bipin Joshi is a software consultant, an author and a yoga mentor having 22+ years of experience in software development. He also conducts online courses in ASP.NET MVC / Core and Design Patterns. He is a published author and has authored or co-authored books for Apress and Wrox press. Having embraced the Yoga way of life he also teaches Ajapa Yoga to interested individuals. To know more about him click here.

Get connected : Twitter  Facebook  Google+  LinkedIn

Posted On : 30 June 2015


Tags : ASP.NET MVC C#