2011-08-25 8 views
29

Estoy viendo esto en nuestro sitio de producción, así como un sitio de prueba pequeño configuré solo para probar esto ...Error en MVC3: las solicitudes nunca exceden el tiempo de espera. Funciona bien para páginas aspx en el mismo proyecto

Básicamente, parece que las solicitudes manejadas por mvc nunca se acabó el tiempo. Establecí un executionTimeout en mi web.config y apagué el modo de depuración. Luego agregué un bucle infinito de thread.sleeps tanto a una página aspx regular como a una página mvc (el loop está en el controlador de la página mvc). La página aspx se agota de forma confiable (HttpException (0x80004005): la solicitud agotó el tiempo de espera), pero la página de mvc simplemente gira para siempre sin agotar el tiempo de espera.

¿Hay configuraciones separadas para mvc (he buscado pero no las he encontrado)? ¿Las solicitudes de mvc no exceden el tiempo de espera por defecto?

Cualquier ayuda sobre esto sería apreciada. Con mucho gusto enviaré un correo electrónico a mi pequeño sitio de prueba si eso ayudaría a alguien.

Editar: Estoy usando MVC3.

contenido de mi web.config:

<?xml version="1.0"?> 

<!-- 
    For more information on how to configure your ASP.NET application, please visit 
    http://go.microsoft.com/fwlink/?LinkId=169433 
    --> 

<configuration> 
    <connectionStrings> 
    <add name="ApplicationServices" 
     connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\aspnetdb.mdf;User Instance=true" 
     providerName="System.Data.SqlClient" /> 
    </connectionStrings> 
    <appSettings> 
    <add key="webpages:Enabled" value="true" /> 
    </appSettings> 

    <system.web> 
     <httpRuntime maxRequestLength="16384" executionTimeout="30" /> 
     <compilation debug="false" targetFramework="4.0"> 
      <assemblies> 
      <add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /> 
      <add assembly="System.Web.Helpers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /> 
      <add assembly="System.Web.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /> 
      <add assembly="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /> 
      <add assembly="System.Web.WebPages, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /> 
      </assemblies> 
     </compilation> 

    <authentication mode="Forms"> 
     <forms loginUrl="~/Account/Login.aspx" timeout="2880" /> 
    </authentication> 

    <membership> 
     <providers> 
     <clear/> 
     <add name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider" connectionStringName="ApplicationServices" 
      enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" 
      maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" 
      applicationName="/" /> 
     </providers> 
    </membership> 

    <profile> 
     <providers> 
     <clear/> 
     <add name="AspNetSqlProfileProvider" type="System.Web.Profile.SqlProfileProvider" connectionStringName="ApplicationServices" applicationName="/"/> 
     </providers> 
    </profile> 

    <roleManager enabled="false"> 
     <providers> 
     <clear/> 
     <add name="AspNetSqlRoleProvider" type="System.Web.Security.SqlRoleProvider" connectionStringName="ApplicationServices" applicationName="/" /> 
     <add name="AspNetWindowsTokenRoleProvider" type="System.Web.Security.WindowsTokenRoleProvider" applicationName="/" /> 
     </providers> 
    </roleManager> 

    </system.web> 

    <system.webServer> 
    <modules runAllManagedModulesForAllRequests="true"/> 
    </system.webServer> 
</configuration> 
+1

¡Esto me está pasando a mí también! ¡Me sorprende que no haya visto a nadie más quejarse de este problema! –

+0

parece un error de framework! – dan

+0

¿de qué sirve esto? ¿Realmente sucede alguna vez en un escenario real? – mare

Respuesta

9

he encontrado la causa de esto, me parece :

Este método está en la clase WrappedAsyncResult, que la clase MvcHandler usa a través de BeginProcessRequest:

public static IAsyncResult BeginSynchronous<TResult>(AsyncCallback callback, object state, Func<TResult> func, object tag) 
{ 
    BeginInvokeDelegate beginDelegate = delegate (AsyncCallback asyncCallback, object asyncState) { 
     SimpleAsyncResult result = new SimpleAsyncResult(asyncState); 
     result.MarkCompleted(true, asyncCallback); 
     return result; 
    }; 
    EndInvokeDelegate<TResult> endDelegate = _ => func(); 
    WrappedAsyncResult<TResult> result = new WrappedAsyncResult<TResult>(beginDelegate, endDelegate, tag); 
    result.Begin(callback, state, -1); 
    return result; 
} 

donde "Begin" es:

public void Begin(AsyncCallback callback, object state, int timeout) 
{ 
    bool completedSynchronously; 
    this._originalCallback = callback; 
    lock (this._beginDelegateLockObj) 
    { 
     this._innerAsyncResult = this._beginDelegate(new AsyncCallback(this.HandleAsynchronousCompletion), state); 
     completedSynchronously = this._innerAsyncResult.CompletedSynchronously; 
     if (!completedSynchronously && (timeout > -1)) 
     { 
      this.CreateTimer(timeout); 
     } 
    } 
    if (completedSynchronously && (callback != null)) 
    { 
     callback(this); 
    } 
} 

EDIT: han llegado con una forma torpe de forzar las acciones del controlador MVC a "tiempo de espera", aunque el mecanismo es un poco desvanecido

public class TimeoutController : Controller 
{ 
    private bool _isExecuting = false; 
    private int _controllerTimeout = 5000; 
    private Thread _executingThread; 
    private readonly object _syncRoot = new object(); 

    protected override void ExecuteCore() 
    { 
     _executingThread = Thread.CurrentThread; 
     ThreadPool.QueueUserWorkItem(o => 
      { 
       Thread.Sleep(_controllerTimeout); 
       if (_isExecuting) 
       { 
        _executingThread.Abort(); 
       } 
      }); 
     base.ExecuteCore(); 
    } 

    protected override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     _isExecuting = true; 
     base.OnActionExecuting(filterContext); 
    } 

    protected override void OnActionExecuted(ActionExecutedContext filterContext) 
    { 
     _isExecuting = false;     
     base.OnActionExecuted(filterContext); 
    } 

    public int ControllerTimeout 
    { 
     get 
     { 
      int retVal; 
      lock(_syncRoot) 
      { 
       retVal = _controllerTimeout; 
      } 
      return retVal; 
     } 
     set 
     { 
      lock(_syncRoot) 
      { 
       _controllerTimeout = value;      
      } 
     } 
    } 
} 
+0

Esta es la única solución que funcionó para mí hasta ahora. –

+0

¿Puede explicar dónde, cómo y qué está haciendo ControllerTimeout? –

+0

Básicamente, obliga a que el subproceso que ejecuta el controlador se cierre después de un período de tiempo de espera especificado; como quemar tu casa para matar a una araña. – JerKimball

2

Debería funcionar cuando se cumplen estas condiciones:

1) El nombre de dominio no es localhost (a prueba de tiempo de espera se debe utilizar "YourComputerName" en lugar de "localhost").

2) El proyecto se compila en modo de lanzamiento.

3) compilation debug = "false"

si se ve aquí por una alternativa (ScriptTimeOut): ASP.NET MVC and httpRuntime executionTimeout

Saludos,
papá

+1

Gracias por la respuesta, pero eso no parece haber solucionado el problema. Ahora estoy usando el nombre de mi computadora en lugar de localhost, lo compilé en modo de lanzamiento en Visual Studio y tengo la depuración establecida en falso en mi web.config. También intenté establecer la propiedad scriptTimeout en mis páginas mvc, pero eso tampoco me ayudó. Creo que esto podría ser un error en el marco. – Scott

+0

¿Has visto el comentario en el otro hilo SO sobre no tener un ~ en la ruta? Tal vez ese es tu problema. Estoy de acuerdo en que debería funcionar en la depuración sin embargo. – whosrdaddy

+0

No estoy usando la etiqueta de ubicación, por lo que no hay una ruta. Solo quiero que este tiempo de espera funcione en un nivel global para páginas mvc y aspx. Con mi configuración actual, funciona bien para las páginas aspx, pero las páginas mvc no se agotarán. – Scott

0

Aún pasando por mí en MVC 4. he enviado esto a microsoft como un error:

https://connect.microsoft.com/VisualStudio/feedback/details/781171/asp-net-mvc-executiontimeout-does-not-work

Actualización:

Microsoft comentó con lo siguiente:

La función de tiempo de espera de ejecución no se aconseja para ser utilizado en aplicaciones MVC . En su lugar, puede establecer HttpContext.Server.ScriptTimeout en el valor de tiempo de espera deseado.A pesar del nombre, esta es una configuración por petición y debe aplicarse a cualquier petición ASP.NET (el "guión" nombre es engañoso)

.

Cuestiones relacionadas