实现IActionResult筛选器运行时错误

本文关键字:运行时错误 筛选 IActionResult 实现 | 更新日期: 2023-09-27 18:20:06

我正在尝试实现这个例子:

堆栈溢出

但是,当我的ASP.NET MVC4应用程序在代码filterContext.RequestContext.HttpContext.Response.Filter = new CdnResponseFilter(filterContext.RequestContext.HttpContext.Response.Filter);行的第一个Action异常消息之后执行任何操作时,它都会不断抛出Filtering is not allowed

根据一些搜索,我尝试将过滤器移动到另一个事件函数,但都没有成功。我还尝试过检查过滤器是否已经应用,如果已经应用,请不要添加新的过滤器。

第一个操作经过了适当的过滤,在执行第二个操作时抛出异常。

代码

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();
    }
}

根据要求,这里是从Global.asax.cs:调用的RegisterGlobalFilters

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());
        }
    }
}

添加完整堆栈跟踪的另一个编辑:

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.<>c__DisplayClass4f.b__49() 
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass4f.b__49() 
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass4f.b__49() 
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass37.b__36(IAsyncResult asyncResult) 
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass25.<>c__DisplayClass2a.b__20()
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass25.b__22(IAsyncResult asyncResult) 
at System.Web.Mvc.Controller.<>c__DisplayClass1d.b__18(IAsyncResult asyncResult) 
at System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass4.b__3(IAsyncResult ar) 
at System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) 
at System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass4.b__3(IAsyncResult ar) 
at System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) 
at System.Web.Mvc.MvcHandler.<>c__DisplayClass8.b__3(IAsyncResult asyncResult) 
at System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass4.b__3(IAsyncResult ar) 
at System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) 
at System.Web.Mvc.HttpHandlerUtil.ServerExecuteHttpHandlerWrapper.<>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)

在试图解决这个问题时,我偶然发现了一件非常奇怪的事情,那就是如果我将OnActionExecute中的Response.Filter的设置包装在try{}catch{}}块中,则页面将正确地使用过滤器进行渲染。这让我觉得系统的其他部分正在尝试过滤不应该过滤的内容。我将在调试器中做一些工作,看看是否不能从这里缩小范围。

实现IActionResult筛选器运行时错误

我通过在注册过滤器期间将过滤器移动到列表的顶部来解决这个问题。如果有人知道为什么这样做,我很想知道,但这里是我的解决方案:

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        if (Settings.Default.CDNEnable)
        {
            filters.Add(new Filters.CDNUrlFilter());
        }
        filters.Add(new HandleErrorAttribute());
        filters.Add(new Filters.InitializeSimpleMembershipAttribute());
        filters.Add(new Filters.RequestTimingFilter());
    }
}

冲突发生在初始化SimpleMembership的第一个Action之后。出于某种原因,一旦发生这种情况,就无法应用其他过滤器。RequestTimingFilter之所以有效,是因为它没有将筛选器应用于请求上下文,它只是存储在每个操作之外的一个定时事件。

我很确定您的CDN过滤器在技术上正在更改您在网站上的路由。SimpleMembership需要Account控制器的路由在初始化时是正确的。

这篇文章使我得出了这个结论。

默认情况下,WebSecurity.InitializeDatabaseConnection()调用位于InitializeSimpleMembershipAttribute类中,并且默认情况下AccountController与此属性一起使用。问题是必须首先调用与AccountController关联的路由才能初始化SimpleMembershipProvider。。。

来源。