我正在尝试实现此示例:
但我的ASP.NET MVC4应用程序在代码行Filtering is not allowed
上的第一个Action异常消息之后执行任何操作时都会继续抛出filterContext.RequestContext.HttpContext.Response.Filter = new CdnResponseFilter(filterContext.RequestContext.HttpContext.Response.Filter);
。
根据一些搜索,我尝试将过滤器移动到另一个事件函数,但它们都没有工作。我还尝试检查过滤器是否已经应用,如果是,则不添加新过滤器。
第一个操作已正确过滤,它正在执行的第二个操作中抛出异常。
代码
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)
在尝试解决这个问题时,我偶然发现了一些非常奇怪的事情,如果我在一个try {} catch {}块中包含OnActionExecute中的Response.Filter设置,那么页面会正确地使用过滤器。这让我觉得系统的其他部分试图被过滤而不应该被过滤。我将在调试器中做一些工作,看看我是否不能从这里缩小范围。
答案 0 :(得分:2)
我通过在注册过滤器期间将过滤器移动到列表顶部来解决这个问题。如果有人知道为什么这有用,我很乐意知道,但这是我的解决方案:
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工作是因为它没有对请求上下文应用过滤器,它只是一个存储在每个动作之外的定时事件。
答案 1 :(得分:2)
我非常确定您的CDN过滤器在技术上会改变您在网站上的路由。 SimpleMembership需要帐户控制器的路由在初始化时才是正确的。
这篇文章是我得出这个结论的原因。
默认情况下,WebSecurity.InitializeDatabaseConnection()调用位于InitializeSimpleMembershipAttribute类中,默认情况下,AccountController将使用此属性进行处理。麻烦的是必须首先调用与AccountController关联的路由,以便初始化SimpleMembershipProvider ...