Как заставить ASP.NET MVC распознавать IHttpAsyncHandler из IRouteHandler.GetHttpHandler ()? - PullRequest
4 голосов
/ 10 ноября 2008

В этом вопросе и ответе я нашел один способ заставить ASP.NET MVC поддерживать асинхронную обработку. Однако я не могу заставить его работать.

По сути, идея заключается в том, чтобы создать новую реализацию IRouteHandler, которая имеет только один метод GetHttpHandler . Метод GetHttpHandler должен возвращать реализацию IHttpAsyncHandler, а не просто IHttpHandler, потому что IHttpAsyncHandler имеет API-шаблон 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();
        }
    }
}

Затем в методе RegisterRoutes файла Global.asax.cs зарегистрируйте этот класс AsyncMvcRouteHandler . public static void RegisterRoutes (маршруты RouteCollection) { routes.IgnoreRoute ( "{ресурс} .axd / {* PathInfo}");

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

Я установил точку останова на ProcessRequest , BeginProcessRequest и EndProcessRequest . Только ProcessRequest выполняется. Другими словами, хотя AsyncMvcHandler реализует IHttpAsyncHandler . ASP.NET MVC этого не знает и просто обрабатывает это как реализацию IHttpHandler.

Как заставить ASP.NET MVC обрабатывать AsyncMvcHandler как IHttpAsyncHandler , чтобы мы могли выполнять асинхронную обработку страниц?

Ответы [ 3 ]

3 голосов
/ 29 января 2009

У меня была такая же проблема, однако я обнаружил, что это потому, что мой обработчик перехвата всех маршрутов:

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

Получал запрос, а не пользовательский маршрут, который я добавил, который имел дело с обработчиком асинхронных маршрутов. Возможно, используя .mvc в своем пользовательском определении маршрута, вы создали различие, чтобы оно использовалось, а не как синхронный универсальный элемент.

2 голосов
/ 12 ноября 2008

После нескольких часов хлопот с кодом я обнаружил проблему.

В моей Visual Studio 2008, когда я нажимаю Ctrl + F5, запускается сервер разработки приложений, и IE открывается для доступа "http://localhost:3573/". В этом случае API синхронизации ProcessRequest вызывается. Трассировка стека выглядит следующим образом.

MyMvcApplication.DLL! MyMvcApplication.AsyncMvcRouteHandler.AsyncMvcHandler.ProcessRequest (System.Web.HttpContext httpContext = {System.Web.HttpContext}) Строка 59 C # System.Web.Mvc.dll! System.Web.Mvc.MvcHttpHandler.VerifyAndProcessRequest (System.Web.IHttpHandler HttpHandler, System.Web.HttpContextBase httpContext) + 0x19 байт
System.Web.Routing.dll! System.Web.Routing.UrlRoutingHandler.ProcessRequest (System.Web.HttpContextBase httpContext) + 0x66 байт
System.Web.Routing.dll! System.Web.Routing.UrlRoutingHandler.ProcessRequest (System.Web.HttpContext httpContext) + 0x28 байт
System.Web.Routing.dll! System.Web.Routing.UrlRoutingHandler.System.Web.IHttpHandler.ProcessRequest (System.Web.HttpContext контекст) + 0x8 байт
MyMvcApplication.DLL! MyMvcApplication._Default.Page_Load (объект отправитель = {ASP.default_aspx}, System.EventArgs e = {System.EventArgs}) Строка 13 + 0x1a байты C #

Однако, когда я изменяю URL в IE на «http://localhost:3573/whatever.mvc",, он попадает в BeginProcessRequest . Трассировка стека выглядит следующим образом.

MyMvcApplication.DLL! MyMvcApplication.AsyncMvcRouteHandler.AsyncMvcHandler.BeginProcessRequest (System.Web.HttpContext context = {System.Web.HttpContext}, System.AsyncCallback cb = {Method = {Пустота OnAsyncHandlerCompletion (System.IAsyncResult)}}, объект extraData = null) Строка 66 C # System.Web.dll! System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute () + 0x249 байт System.Web.dll! System.Web.HttpApplication.ExecuteStep (System.Web.HttpApplication.IExecutionStep шаг = {} System.Web.HttpApplication.CallHandlerExecutionStep, ref bool completeSynchronously = true) + 0x9c байт
System.Web.dll! System.Web.HttpApplication.ApplicationStepManager.ResumeSteps (System.Exception ошибка) + 0x133 байта
System.Web.dll! System.Web.HttpApplication.System.Web.IHttpAsyncHandler.BeginProcessRequest (System.Web.HttpContext контекст, System.AsyncCallback cb, объект extraData) + 0x7c байт
System.Web.dll! System.Web.HttpRuntime.ProcessRequestInternal (System.Web.HttpWorkerRequest WR = {} Microsoft.VisualStudio.WebHost.Request) + 0x17c байт System.Web.dll! System.Web.HttpRuntime.ProcessRequestNoDemand (System.Web.HttpWorkerRequest wr) + 0x63 байта
System.Web.dll! System.Web.HttpRuntime.ProcessRequest (System.Web.HttpWorkerRequest wr) + 0x47 байт
WebDev.WebHost.dll! Microsoft.VisualStudio.WebHost.Request.Process () + 0xf1 байт WebDev.WebHost.dll! Microsoft.VisualStudio.WebHost.Host.ProcessRequest (Microsoft.VisualStudio.WebHost.Connection conn) + 0x4e байт

Кажется, что только URL с суффиксом ".mvc" может вызвать асинхронный API.

0 голосов
/ 10 ноября 2008

Я пытался сделать это в прошлом, мне удается либо сделать представление для визуализации, и тогда все асинхронные задачи завершатся. Или асинхронные задачи для завершения, но представление не будет отображаться.

Я создал RouteCollectionExtensions на основе исходного кода MVC. В моем AsyncMvcHandler у меня был пустой метод (без исключения) для ProcessMethod.

...