[TimeoutFilter] public abstract class BaseController: Controller { } public class IntegrationTestController : BaseController { [HttpGet] public ActionResult TimeoutSeconds() { return Content(HttpContext.Server.ScriptTimeout.ToString(CultureInfo.InvariantCulture)); } [HttpGet] public ActionResult ForceTimeout() { var timeoutWindow = TimeoutFilter.TimeoutSeconds; Thread.Sleep((timeoutWindow + 5) * 1000); return Content("This should never get returned,mwahahaaa!"); } }
对于我的测试场景,我在TimeoutFilter中使用5秒的配置设置,我知道这是正常工作,因为当我的测试调用TimeoutSeconds时,我得到正确的值为5,但是当测试调用ForceTimeout时,我得到一个HTTP响应200和我的“从未退回”的文字.
和过滤器:
public class TimeoutFilter : ActionFilterAttribute { internal const string TimeoutSecondsSettingsKey = "MvcActionTimeoutSeconds"; internal static int TimeoutSeconds; public TimeoutFilter() { TimeoutSeconds = int.Parse(ConfigurationManager.AppSettings[TimeoutSecondsSettingsKey]); } public override void OnActionExecuting(ActionExecutingContext filterContext) { filterContext.Controller.ControllerContext.HttpContext.Server.ScriptTimeout = TimeoutSeconds; base.OnActionExecuting(filterContext); } }
解决方法
<configuration> <system.web> <compilation debug="false" targetFramework="4.5"/> ...
它继续返回文本“这不应该返回”,而不是在Thread.Sleep中超时.
还值得注意的是,我还扩展了Thread.Sleep,远远超出了Server.ScriptTimeout的默认值110秒,但是最终还是返回相同的文本而不是超时.
然后我尝试在web.config中设置executionTimeout:
<configuration> <system.web> <httpRuntime targetFramework="4.5" executionTimeout="5"/> ...
如果要现在向TimeoutFilter添加一个断点,您将观察到ScriptTimeout值已从web.config设置为executionTimeout值.唉,这对我来说还是不行(不管debug =“false”).
然后我遇到了关于ScriptTimeout的this link,executionTimeout没有使用与您所描述的类似设置.该帖子中的第一个回复描述了使用debug =“false”,并且还提到超时将延迟5到15秒.即使使用大的Thread.Sleep值,我仍然没有运气.本文中的第二个回复表明,executionTimeout配置设置是ScriptTimeout属性的替代(这显然是在经典ASP中使用的COM接口).此回复表明,无法设置特定的超时,而不使用您自己的超时逻辑.
此外,然后我碰到了following (more recent) link,其中第一个回复建议在MVC中关闭超时.进一步的答复表明,这是因为MVCHandler
(它选择将处理HTTPRequest的控制器)是IHttpAsyncHandler,因为它可能因此执行另一个请求(这是使用异步请求的点),因此内部切换时间关闭(这是我从阅读这个链接收集的).它必须使用直接asp.net,尽管使用ScriptTimeout似乎是在this answer被接受的方式.
该链接表明,添加以下行将允许它工作(但不在中等信任应用程序中):
System.Web.HttpContext.Current.GetType().GetField("_timeoutState",System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).SetValue(System.Web.HttpContext.Current,1);
因此,将TimeoutFilter OnActionExecuting()更改为:
public override void OnActionExecuting(ActionExecutingContext filterContext) { System.Web.HttpContext.Current.GetType().GetField("_timeoutState",1); base.OnActionExecuting(filterContext); }
并设置web.config:
<configuration> <system.web> <compilation debug="false" targetFramework="4.5"/> <httpRuntime targetFramework="4.5" executionTimeout="5"/> ...
允许超时工作,但在第一篇文章中提到了稍微延迟5秒.
注意:使用此方法不允许您在过滤器中设置ScriptTimeout属性.尝试设置ScriptTimeout并覆盖web.config中设置的值似乎不起作用.