OnActionExecuting запускает несколько раз
Я не уверен, что это правильный путь решения проблемы, которую мне нужно решить... однако в фильтре действий OnActionExecuting, который я создал, я установил cookie с различными значениями. Одно из этих значений используется, чтобы определить, посещает ли пользователь веб-сайт в первый раз. Если они - новый посетитель, тогда я устанавливаю ViewBag с некоторыми данными, чтобы я мог отобразить это в моем представлении.
У меня проблема в том, что в некоторых из моих действий контроллера я выполняю RedirectToAction. В результате OnActionExecuting запускается дважды: один раз для исходного действия, а затем второй раз, когда запускается новое действие.
<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? Фильтр действий используется на нескольких контроллерах.
3 ответа
Вы можете сохранить некоторое значение флага в TempData
сбор контроллера при первом выполнении и, если это значение представлено, пропустить логику фильтра:
if (filterContext.Controller.TempData["MyActionFilterAttribute_OnActionExecuting"] == null)
{
filterContext.Controller.TempData["MyActionFilterAttribute_OnActionExecuting"] = true;
}
Была такая же проблема. Разрешается переопределением свойства AllowMultiple:
public override bool AllowMultiple { get { return false; } }
public override void OnActionExecuting(HttpActionContext actionContext)
{
//your logic here
base.OnActionExecuting(actionContext);
}
Вы можете вернуть фактическое действие вместо перенаправления на новое действие. Таким образом, вы не вызываете http-запрос, тем самым не вызывая onactionexecuting (я считаю)
Старый вопрос, но я только что разобрался с этим, поэтому подумал, что добавлю свой ответ. После некоторого расследования я обнаружил, что это происходило только на конечных точках, которые возвращали представление (т.е. 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();
}