Note that there are some explanatory texts on larger screens.

plurals
  1. POImplementing an IActionResult Filter run time error
    primarykey
    data
    text
    <p>I am trying to implement this example: </p> <p><a href="https://stackoverflow.com/a/6892794/1561465">Stack Overflow</a></p> <p>But my ASP.NET MVC4 app keeps throwing <code>Filtering is not allowed</code> when it executes anything after the first Action exception messages on the line of code <code>filterContext.RequestContext.HttpContext.Response.Filter = new CdnResponseFilter(filterContext.RequestContext.HttpContext.Response.Filter);</code>. </p> <p>Based on some searching I've tried moving the filter to another event function but none of them have worked. I have also tried checking if the filter is already applied and if so don't add a new one.</p> <p>The first action is properly filtered, it's on the second action being executed that it throws the exception.</p> <p>Code</p> <pre><code>public class CDNUrlFilter : IActionFilter, IResultFilter { public void OnActionExecuting(ActionExecutingContext filterContext) { } public void OnActionExecuted(ActionExecutedContext filterContext) { filterContext.RequestContext.HttpContext.Response.Filter = new CdnResponseFilter(filterContext.RequestContext.HttpContext.Response.Filter); } public void OnResultExecuting(ResultExecutingContext filterContext) { } public void OnResultExecuted(ResultExecutedContext filterContext) { } } public class CdnResponseFilter : MemoryStream { private Stream Stream { get; set; } public CdnResponseFilter(Stream stream) { Stream = stream; } public override void Write(byte[] buffer, int offset, int count) { var data = new byte[count]; Buffer.BlockCopy(buffer, offset, data, 0, count); string html = Encoding.Default.GetString(buffer); html = Regex.Replace(html, "src=\"/Content/([^\"]+)\"", FixUrl, RegexOptions.IgnoreCase); html = Regex.Replace(html, "href=\"/Content/([^\"]+)\"", FixUrl, RegexOptions.IgnoreCase); html = Regex.Replace(html, "src=\"/Images/([^\"]+)\"", FixUrl, RegexOptions.IgnoreCase); html = Regex.Replace(html, "href=\"/Images/([^\"]+)\"", FixUrl, RegexOptions.IgnoreCase); byte[] outData = Encoding.Default.GetBytes(html); Stream.Write(outData, 0, outData.GetLength(0)); } private static string FixUrl(Match match) { if (match.ToString().Contains("src")) { return String.Format("{0}", match.ToString()); } else if (match.ToString().Contains("href")) { return String.Format("href=\"{0}content{1}", Settings.Default.CDNDomain, match.ToString().Replace("href=\"", "")); } return match.ToString(); } } </code></pre> <p>As requested here is the RegisterGlobalFilters which is called from Global.asax.cs:</p> <pre><code>public class FilterConfig { public static void RegisterGlobalFilters(GlobalFilterCollection filters) { filters.Add(new HandleErrorAttribute()); filters.Add(new Filters.InitializeSimpleMembershipAttribute()); filters.Add(new Filters.RequestTimingFilter()); if (Settings.Default.CDNEnable) { filters.Add(new Filters.CDNUrlFilter()); } } } </code></pre> <p>Another edit to add the complete stack trace:</p> <pre><code>Stack Trace at System.Web.HttpResponse.set_Filter(Stream value) at POSGuys.Filters.CDNUrlFilter.OnActionExecuted(ActionExecutedContext filterContext) in c:\Users\skatir\Documents\BitBucket\posguys\Filters\CDNUrlFilter.cs:line 20 at System.Web.Mvc.Async.AsyncControllerActionInvoker.&lt;&gt;c__DisplayClass4f.b__49() at System.Web.Mvc.Async.AsyncControllerActionInvoker.&lt;&gt;c__DisplayClass4f.b__49() at System.Web.Mvc.Async.AsyncControllerActionInvoker.&lt;&gt;c__DisplayClass4f.b__49() at System.Web.Mvc.Async.AsyncControllerActionInvoker.&lt;&gt;c__DisplayClass37.b__36(IAsyncResult asyncResult) at System.Web.Mvc.Async.AsyncControllerActionInvoker.&lt;&gt;c__DisplayClass25.&lt;&gt;c__DisplayClass2a.b__20() at System.Web.Mvc.Async.AsyncControllerActionInvoker.&lt;&gt;c__DisplayClass25.b__22(IAsyncResult asyncResult) at System.Web.Mvc.Controller.&lt;&gt;c__DisplayClass1d.b__18(IAsyncResult asyncResult) at System.Web.Mvc.Async.AsyncResultWrapper.&lt;&gt;c__DisplayClass4.b__3(IAsyncResult ar) at System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) at System.Web.Mvc.Async.AsyncResultWrapper.&lt;&gt;c__DisplayClass4.b__3(IAsyncResult ar) at System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) at System.Web.Mvc.MvcHandler.&lt;&gt;c__DisplayClass8.b__3(IAsyncResult asyncResult) at System.Web.Mvc.Async.AsyncResultWrapper.&lt;&gt;c__DisplayClass4.b__3(IAsyncResult ar) at System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) at System.Web.Mvc.HttpHandlerUtil.ServerExecuteHttpHandlerWrapper.&lt;&gt;c__DisplayClass4.b__3() at System.Web.Mvc.HttpHandlerUtil.ServerExecuteHttpHandlerWrapper.Wrap[TResult](Func`1 func) at System.Web.HttpServerUtility.ExecuteInternal(IHttpHandler handler, TextWriter writer, Boolean preserveForm, Boolean setPreviousPage, VirtualPath path, VirtualPath filePath, String physPath, Exception error, String queryStringOverride) Target Site Void set_Filter(System.IO.Stream) </code></pre> <p>While trying to solve this I've stumbled upon something very weird which is if I wrap the setting of the Response.Filter in OnActionExecute in a try{}catch{} block the page renders using the filter properly. This is making me think that some other part of the system is try to be filtered that shouldn't be. I'm going to do some work in the debugger and see if I can't narrow it down from here.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload