Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to I replace URLs in rendered HTML using an ASP.NET MVC ActionFilter

I'm trying to create an ActionFilter to replace some text in my HTML. Basically when the server is using SSL I want to replace references to my CDN (http://cdn.example.com) with references directly to my server (https://www.example.com). So the structure is something like this (I assume OnResultExecuted is where I should start):

public class CdnSslAttribute : ActionFilterAttribute
{
    public override void OnResultExecuted(ResultExecutedContext filterContext)
    {
        if(filterContext.HttpContext.Request.IsSecureConnection)
        {
            // when the connection is secure,
            // somehow replace all instances of http://cdn.example.com
            // with https://www.example.com
        }
    }
}

This would be used in my secure controllers:

[CdnSsl] 
public class SecureController : Controller
{
}

The reason I want to do this is my CDN doesn't support SSL. And there are references in the Master pages to CDN resources. Example:

<link href="http://cdn.example.com/Content/base.css" rel="stylesheet" type="text/css" />
like image 644
Keltex Avatar asked Nov 21 '25 20:11

Keltex


1 Answers

I ended up using a variation on this blog post:

http://arranmaclean.wordpress.com/2010/08/10/minify-html-with-net-mvc-actionfilter/

with my own filter:

public class CdnSslAttribute : ActionFilterAttribute
{
    public override void OnResultExecuted(ResultExecutedContext filterContext)
    {
        if (filterContext.HttpContext.Request.IsSecureConnection)
        {
            var response = filterContext.HttpContext.Response;
            response.Filter = new CdnSslFilter(response.Filter);
        }
    }
}

Then the filter looks like this (some code omitted for brevity):

public class CdnSslFilter : Stream
{
    private Stream _shrink;
    private Func<string, string> _filter;

    public CdnSslFilter(Stream shrink)
    {
        _shrink = shrink;
        _filter = s => Regex.Replace(s,@"http://cdn\.","https://www.", RegexOptions.IgnoreCase);
    }

    //overridden functions omitted for clarity. See above blog post.

    public override void Write(byte[] buffer, int offset, int count)
    {
        // capture the data and convert to string 
        byte[] data = new byte[count];
        Buffer.BlockCopy(buffer, offset, data, 0, count);
        string s = Encoding.Default.GetString(buffer);

        // filter the string
        s = _filter(s);

        // write the data to stream 
        byte[] outdata = Encoding.Default.GetBytes(s);
        _shrink.Write(outdata, 0, outdata.GetLength(0));
    }
}
like image 98
Keltex Avatar answered Nov 23 '25 16:11

Keltex



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!