Pregunta

En esta question & amp; respuesta , encontré una forma de hacer que ASP.NET MVC admita el procesamiento asincrónico. Sin embargo, no puedo hacer que funcione.

Básicamente, la idea es crear una nueva implementación de IRouteHandler que solo tenga un método GetHttpHandler . El método GetHttpHandler debería devolver una implementación IHttpAsyncHandler en lugar de solo IHttpHandler, porque IHttpAsyncHandler tiene API de patrón Begin / EndXXXX.

public class AsyncMvcRouteHandler : IRouteHandler
{
    public IHttpHandler GetHttpHandler(RequestContext requestContext)
    {
        return new AsyncMvcHandler(requestContext);
    }

    class AsyncMvcHandler : IHttpAsyncHandler, IRequiresSessionState
    {
        public AsyncMvcHandler(RequestContext context)
        {
        }

        // IHttpHandler members
        public bool IsReusable { get { return false; } }
        public void ProcessRequest(HttpContext httpContext) { throw new NotImplementedException(); }

        // IHttpAsyncHandler members
        public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
        {
            throw new NotImplementedException();
        }

        public void EndProcessRequest(IAsyncResult result)
        {
            throw new NotImplementedException();
        }
    }
}

Luego, en el método RegisterRoutes del archivo Global.asax.cs, registre esta clase AsyncMvcRouteHandler .         public static void RegisterRoutes (rutas RouteCollection)         {             routes.IgnoreRoute (" {resource} .axd / {* pathInfo} ");

        routes.Add(new Route("{controller}/{action}/{id}", new AsyncMvcRouteHandler())
        {
            Defaults = new RouteValueDictionary(new { controller = "Home", action = "Index", id = "" }),
        });
    }

Establecí el punto de interrupción en ProcessRequest , BeginProcessRequest y EndProcessRequest . Solo se ejecuta ProcessRequest . En otras palabras, aunque AsyncMvcHandler implementa IHttpAsyncHandler . ASP.NET MVC no lo sabe y solo lo maneja como una implementación IHttpHandler.

¿Cómo hacer que ASP.NET MVC trate a AsyncMvcHandler como IHttpAsyncHandler para que podamos tener un procesamiento de página asincrónico?

¿Fue útil?

Solución 2

Después de horas de problemas con el código, descubrí el problema.

En mi Visual Studio 2008, cuando presiono Ctrl + F5, se inicia el servidor de desarrollo de aplicaciones y se abre IE para acceder " http: // localhost: 3573 / " ;. En este caso, se invoca la API de sincronización ProcessRequest . El seguimiento de la pila es así.

  
    

MyMvcApplication.DLL! MyMvcApplication.AsyncMvcRouteHandler.AsyncMvcHandler.ProcessRequest (System.Web.HttpContext     httpContext =     {System.Web.HttpContext}) Línea 59 C #       System.Web.Mvc.dll! System.Web.Mvc.MvcHttpHandler.VerifyAndProcessRequest (System.Web.IHttpHandler     httpHandler,     System.Web.HttpContextBase     httpContext) + 0x19 bytes
      System.Web.Routing.dll! System.Web.Routing.UrlRoutingHandler.ProcessRequest (System.Web.HttpContextBase     httpContext) + 0x66 bytes
      System.Web.Routing.dll! System.Web.Routing.UrlRoutingHandler.ProcessRequest (System.Web.HttpContext     httpContext) + 0x28 bytes
      System.Web.Routing.dll! System.Web.Routing.UrlRoutingHandler.System.Web.IHttpHandler.ProcessRequest (System.Web.HttpContext     contexto) + 0x8 bytes
      MyMvcApplication.DLL! MyMvcApplication._Default.Page_Load (objeto     remitente = {ASP.default_aspx},     System.EventArgs e =     {System.EventArgs}) Línea 13 + 0x1a     bytes C #

  

Sin embargo, cuando cambio la URL en IE para que sea " http: // localhost: 3573 / lo que sea. mvc " ;, toca el BeginProcessRequest . El seguimiento de la pila es así.

  
    

MyMvcApplication.DLL! MyMvcApplication.AsyncMvcRouteHandler.AsyncMvcHandler.BeginProcessRequest (System.Web.HttpContext     contexto = {System.Web.HttpContext},     System.AsyncCallback cb = {Método =     {Vacío     OnAsyncHandlerCompletion (System.IAsyncResult)}},     objeto extraData = nulo) Línea 66 C #       System.Web.dll! System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute ()     + 0x249 bytes System.Web.dll! System.Web.HttpApplication.ExecuteStep (System.Web.HttpApplication.IExecutionStep     paso =     {System.Web.HttpApplication.CallHandlerExecutionStep},     ref bool completeSynchronously =     verdadero) + 0x9c bytes
      System.Web.dll! System.Web.HttpApplication.ApplicationStepManager.ResumeSteps (System.Exception     error) + 0x133 bytes
      System.Web.dll! System.Web.HttpApplication.System.Web.IHttpAsyncHandler.BeginProcessRequest (System.Web.HttpContext     contexto, System.AsyncCallback cb,     object extraData) + 0x7c bytes
      System.Web.dll! System.Web.HttpRuntime.ProcessRequestInternal (System.Web.HttpWorkerRequest     wr =     {Microsoft.VisualStudio.WebHost.Request})     + 0x17c bytes System.Web.dll! System.Web.HttpRuntime.ProcessRequestNoDemand (System.Web.HttpWorkerRequest     wr) + 0x63 bytes
      System.Web.dll! System.Web.HttpRuntime.ProcessRequest (System.Web.HttpWorkerRequest     wr) + 0x47 bytes
      WebDev.WebHost.dll! Microsoft.VisualStudio.WebHost.Request.Process ()     + 0xf1 bytes WebDev.WebHost.dll! Microsoft.VisualStudio.WebHost.Host.ProcessRequest (Microsoft.VisualStudio.WebHost.Connection     conn) + 0x4e bytes

  

Parece que solo url con " .mvc " sufijo puede hacer que se invoque API asíncrona.

Otros consejos

Tuve el mismo problema, sin embargo, descubrí que era porque mi controlador de captura de todas las rutas:

routes.MapRoute(
    "Default",                                                  
    "{controller}/{action}",                           
    new { controller = "Home", action = "Index" }  
);

Estaba recogiendo la solicitud, no la ruta personalizada que agregué que trataba con el controlador de ruta asíncrono. Quizás al usar el .mvc en su definición de ruta personalizada, creó una distinción para que se usara en lugar del síncrono general.

He intentado hacer esto en el pasado, me las arreglé para obtener la vista y luego todas las tareas asíncronas terminarían. O las tareas asíncronas para finalizar pero la vista no se procesará.

Creé un RouteCollectionExtensions basado en el código MVC original. En mi AsyncMvcHandler, tenía un método vacío (sin excepción) para ProcessMethod.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top