ASP.NET MVC 生命周期 - 每个页面请求做一些工作
Posted
技术标签:
【中文标题】ASP.NET MVC 生命周期 - 每个页面请求做一些工作【英文标题】:ASP.NET MVC Lifecycle - Do Some Work Once Per Page Request 【发布时间】:2015-01-21 23:04:29 【问题描述】:我想针对 .NET MVC Web 应用程序的每个 Web 请求执行一些工作。具体来说,我想为每个页面加载在数据库中创建一个日志条目。
在重写的 Controller 类 Controller.Initialize()
方法中执行此工作不起作用,因为 new controller is created with every call to @html.Action()。因此,如果从视图调用子操作,那么我最终会出现双重日志记录——这不是我想要的。
如何在 MVC 生命周期中插入一些工作,以便每个页面请求执行一次?
【问题讨论】:
在 global.asax 中尝试BeginRequest
事件
@VsevolodGoloviznin Try BeginRequest event in global.asax
BeginRequest 事件也会在单个页面加载中被多次调用。
Vsevolod,你的意思是Application_BeginRequest吗?我刚试过。不,不是每个网络请求都调用该方法。
请记住,MVC 中没有页面之类的东西。您应该根据控制器操作重新制定您的要求。然后,您必须明确要记录哪些控制器操作,哪些不记录。
@JohnSaunders,是的,标题可能是“根据 Web 请求做一些工作”。
【参考方案1】:
您可以使用 OnActionExecuting 或 OnActionExecuted。
例如,
public class HomeController : Controller
[LogActionFilter]
public ActionResult Index()
return View();
public class LogActionFilterAttribute : ActionFilterAttribute
public override void OnActionExecuting(ActionExecutingContext filterContext)
// If you register globally, you need this check.
if (!filterContext.IsChildAction)
Log("OnActionExecuting", filterContext.RouteData);
base.OnActionExecuting(filterContext);
public override void OnActionExecuted(ActionExecutedContext filterContext)
// If you register globally, you need this check.
if (!filterContext.IsChildAction)
Log("OnActionExecuted", filterContext.RouteData);
base.OnActionExecuted(filterContext);
private void Log(string methodName, RouteData routeData)
var controllerName = routeData.Values["controller"];
var actionName = routeData.Values["action"];
var message = String.Format("0 controller:1 action:2", methodName, controllerName, actionName);
Debug.WriteLine(message, "Action Filter Log");
【讨论】:
嗨@Win,这可能有效;我曾考虑创建一个新的 ActionFilterAttribute。但我相信我必须对许多现有的控制器操作进行装饰(应用这个新属性)。对吗? 是的。理想情况下,您只需将 LogActionFilter 添加到重要的 Action 方法中。换句话说,您不想记录每个操作方法,因为记录成本很高。 @Michael,您不必将属性应用到每个控制器,您可以全局注册。 @Michael Craig 是正确的。如果您在全球范围内注册,请确保选中 IsChildAction。我更新了答案。 @Win,创建一个新的ActionFilterAttribute
看起来也是一个不错的解决方案。 :) @Craig W. 我不知道我可以在全球范围内注册它。感谢您的帮助!【参考方案2】:
如果操作是子操作,您可以签入Initialize
。
ControllerContext.IsChildAction
【讨论】:
尝试protected override void Initialize()
中的if (!ControllerContext.IsChildAction)
sn-p 不起作用,因为ControllerContext 为空。
Romias,我再次探讨了您的建议。我注意到ControllerContext.IsChildAction
是 在protected override void OnActionExecuted()
中可用。
而不是在 Initialize... 中创建一个 GlobalFilter,并在 Global.asax 中注册它
OnActionExecuted 在开始渲染视图之前以及将模型传递给视图(模型)之后触发。所以在那一刻你可以记录模型本身的信息(例如序列化)。
谢谢。在protected override void OnActionExecuted()
中使用ControllerContext.IsChildAction
对我有用。以上是关于ASP.NET MVC 生命周期 - 每个页面请求做一些工作的主要内容,如果未能解决你的问题,请参考以下文章