Come fare in modo che ASP.NET MVC riconosca IHttpAsyncHandler da IRouteHandler.GetHttpHandler ()?
-
07-07-2019 - |
Domanda
In questa question & amp; risposta , ho trovato un modo per fare in modo che ASP.NET MVC supportasse l'elaborazione asincrona. Tuttavia, non riesco a farlo funzionare.
Fondamentalmente, l'idea è quella di creare una nuova implementazione di IRouteHandler che ha un solo metodo GetHttpHandler . Il metodo GetHttpHandler dovrebbe restituire un'implementazione IHttpAsyncHandler anziché solo IHttpHandler, poiché IHttpAsyncHandler ha un'API modello 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();
}
}
}
Quindi, nel metodo RegisterRoutes del file Global.asax.cs, registra questa classe AsyncMvcRouteHandler . RegisterRoutes vuoto statico pubblico (route RouteCollection) { routes.IgnoreRoute (" {resource} axd / {*} pathinfo ");
routes.Add(new Route("{controller}/{action}/{id}", new AsyncMvcRouteHandler())
{
Defaults = new RouteValueDictionary(new { controller = "Home", action = "Index", id = "" }),
});
}
Ho impostato il punto di interruzione su ProcessRequest , BeginProcessRequest e EndProcessRequest . Viene eseguito solo ProcessRequest . In altre parole, anche se AsyncMvcHandler implementa IHttpAsyncHandler . ASP.NET MVC non lo sa e lo gestisce come un'implementazione IHttpHandler.
Come fare in modo che ASP.NET MVC tratti AsyncMvcHandler come IHttpAsyncHandler in modo da poter avere l'elaborazione asincrona della pagina?
Soluzione 2
Dopo ore di seccature con il codice, ho scoperto il problema.
Nel mio Visual Studio 2008, quando premo Ctrl + F5, viene avviato Application Development Server e IE viene visualizzato per accedere a " http: // localhost: 3573 / " ;. In questo caso, viene richiamata l'API di sincronizzazione ProcessRequest . La traccia dello stack è così.
MyMvcApplication.DLL! MyMvcApplication.AsyncMvcRouteHandler.AsyncMvcHandler.ProcessRequest (System.Web.HttpContext httpContext = {System.Web.HttpContext}) Riga 59 C # System.Web.Mvc.dll! System.Web.Mvc.MvcHttpHandler.VerifyAndProcessRequest (System.Web.IHttpHandler HttpHandler, System.Web.HttpContextBase httpContext) + 0x19 byte
System.Web.Routing.dll! System.Web.Routing.UrlRoutingHandler.ProcessRequest (System.Web.HttpContextBase httpContext) + 0x66 byte
System.Web.Routing.dll! System.Web.Routing.UrlRoutingHandler.ProcessRequest (System.Web.HttpContext httpContext) + 0x28 byte
System.Web.Routing.dll! System.Web.Routing.UrlRoutingHandler.System.Web.IHttpHandler.ProcessRequest (System.Web.HttpContext contesto) + 0x8 byte
MyMvcApplication.DLL! MyMvcApplication._Default.Page_Load (oggetto mittente = {ASP.default_aspx}, System.EventArgs e = {System.EventArgs}) Riga 13 + 0x1a byte C #
Tuttavia, quando cambio l'URL in IE per essere " http: // localhost: 3573 / qualunque. mvc " ;, colpisce il BeginProcessRequest . La traccia dello stack è così.
MyMvcApplication.DLL! MyMvcApplication.AsyncMvcRouteHandler.AsyncMvcHandler.BeginProcessRequest (System.Web.HttpContext context = {System.Web.HttpContext}, System.AsyncCallback cb = {Metodo = {Void OnAsyncHandlerCompletion (System.IAsyncResult)}}, object extraData = null) Riga 66 C # System.Web.dll! System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute () + 0x249 byte System.Web.dll! System.Web.HttpApplication.ExecuteStep (System.Web.HttpApplication.IExecutionStep step = {} System.Web.HttpApplication.CallHandlerExecutionStep, ref bool completatoSincrono = = true) + 0x9c byte
System.Web.dll! System.Web.HttpApplication.ApplicationStepManager.ResumeSteps (System.Exception errore) + 0x133 byte
System.Web.dll! System.Web.HttpApplication.System.Web.IHttpAsyncHandler.BeginProcessRequest (System.Web.HttpContext contesto, System.AsyncCallback cb, oggetto extraData) + 0x7c byte
System.Web.dll! System.Web.HttpRuntime.ProcessRequestInternal (System.Web.HttpWorkerRequest wr = {} Microsoft.VisualStudio.WebHost.Request) + 0x17c byte System.Web.dll! System.Web.HttpRuntime.ProcessRequestNoDemand (System.Web.HttpWorkerRequest wr) + 0x63 byte
System.Web.dll! System.Web.HttpRuntime.ProcessRequest (System.Web.HttpWorkerRequest wr) + 0x47 byte
WebDev.WebHost.dll! Microsoft.VisualStudio.WebHost.Request.Process () + 0xf1 byte WebDev.WebHost.dll! Microsoft.VisualStudio.WebHost.Host.ProcessRequest (Microsoft.VisualStudio.WebHost.Connection conn) + 0x4e byte
Sembra che solo l'URL con " .mvc " il suffisso può far invocare l'API asincrona.
Altri suggerimenti
Ho avuto lo stesso problema, tuttavia ho scoperto che era perché il mio gestore di tutte le rotte cattura:
routes.MapRoute(
"Default",
"{controller}/{action}",
new { controller = "Home", action = "Index" }
);
Stava raccogliendo la richiesta, non il percorso personalizzato che ho aggiunto che si occupava del gestore del percorso asincrono. Forse usando il .mvc nella definizione del tuo percorso personalizzato hai creato una distinzione in modo che fosse usato piuttosto che il sincrono catch-all.
Ho provato a farlo in passato, riesco a ottenere la visualizzazione per il rendering e quindi tutte le attività asincrone sarebbero finite. O le attività asincrone devono essere completate ma la vista non viene visualizzata.
Ho creato un RouteCollectionExtensions basato sul codice MVC originale. Nel mio AsyncMvcHandler, avevo un metodo vuoto (nessuna eccezione) per ProcessMethod.