我不确定这是否是我需要解决的问题的正确方法…然而,在我创建的onactionexecution动作过滤器中,我设置了一个具有各种值的cookie。其中一个值用于确定用户是否是第一次访问该网站。如果他们是一个新的访问者,那么我用一些数据设置ViewBag,这样我就可以在我的视图中显示这些数据。
我的问题是,在我的一些控制器动作我执行一个RedirectToAction。结果是onactionexecution被触发了两次,第一次是原始动作,第二次是在它触发新动作的时候。
<HttpGet()>
Function Index(ByVal PageID As String) As ActionResult
Dim wo As WebPage = Nothing
Try
wp = WebPages.GetWebPage(PageID)
Catch sqlex As SqlException
Throw
Catch ex As Exception
Return RedirectToAction("Index", New With {.PageID = "Home"})
End If
End Try
Return View("WebPage", wp)
End Function
这是个典型的例子。我有一个数据驱动的网站,获得基于指定的PageID数据库的网页。如果在数据库中找不到该页,则将用户重定向到主页。
是否有可能以任何方式防止双重射击或有更好的方法来设置cookie?动作过滤器用于多个控制器
有同样的问题。通过重写属性AllowMultiple:
解决public override bool AllowMultiple { get { return false; } }
public override void OnActionExecuting(HttpActionContext actionContext)
{
//your logic here
base.OnActionExecuting(actionContext);
}
您可以在第一次执行时将一些标志值保存到控制器的TempData
集合中,如果该值出现,则跳过过滤器逻辑:
if (filterContext.Controller.TempData["MyActionFilterAttribute_OnActionExecuting"] == null)
{
filterContext.Controller.TempData["MyActionFilterAttribute_OnActionExecuting"] = true;
}
您可以返回实际操作,而不是重定向到新操作。这样,您就不会引起http请求,从而不会触发onactionexecution(我相信)
老问题,但我刚刚处理了这个问题,所以我想我应该给出我的答案。经过一番调查,我发现这只发生在返回视图的端点上(即return View()
)。有多个OnActionExecuting
被触发的唯一端点是由部分视图组成的HTML视图(即return PartialView(...)
),因此单个请求被"执行"多次。
我将我的ActionFilterAttribute全局应用到所有端点,除了我刚才描述的视图端点外,它在所有其他端点上都能正常工作。解决方案是创建一个附加属性,有条件地应用于部分视图端点。
// Used specifically to ignore the GlobalFilterAttribute filter on an endpoint
public class IgnoreGlobalFilterAttribute : Attribute { }
public class GlobalFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
// Does not apply to endpoints decorated with Ignore attribute
if (!filterContext.ActionDescriptor.GetCustomAttributes(typeof(IgnoreGlobalFilterAttribute), false).Any())
{
// ... attribute logic here
}
}
}
然后在局部视图端点
[HttpGet]
[AllowAnonymous]
[IgnoreGlobalFilter] //HERE this keeps the attribute from firing again
public ActionResult GetPartialView()
{
// partial view logic
return PartialView();
}