ASP.NET MVCでIRouteHandler.GetHttpHandler()からIHttpAsyncHandlerを認識させる方法は?
-
07-07-2019 - |
質問
この質問&回答、ASP.NET MVCが非同期処理をサポートする方法を見つけました。ただし、機能させることはできません。
基本的には、1つのメソッド GetHttpHandler のみを持つIRouteHandlerの新しい実装を作成することです。 IHttpAsyncHandlerにはBegin / EndXXXXパターンAPIがあるため、 GetHttpHandler メソッドは、IHttpHandlerだけでなくIHttpAsyncHandler実装を返す必要があります。
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();
}
}
}
次に、Global.asax.csファイルのRegisterRoutesメソッドで、このクラスを登録します AsyncMvcRouteHandler 。 public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute(" {resource} .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 として処理して、非同期ページ処理を行えるようにする方法
解決 2
コードに何時間も苦労した後、問題を発見しました。
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#
ただし、IEでURLを" http:// localhost:3573 / whateverに変更すると、 mvc "、 BeginProcessRequest にヒットします。スタックトレースは次のようになります。
MyMvcApplication.DLL!MyMvcApplication.AsyncMvcRouteHandler.AsyncMvcHandler.BeginProcessRequest(System.Web.HttpContext コンテキスト= {System.Web.HttpContext}、 System.AsyncCallback cb = {メソッド= {無効 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 completedSynchronously = 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バイト
" .mvc"を含むURLのみサフィックスは非同期APIを呼び出すことができます。
他のヒント
同じ問題を抱えていましたが、それはすべてのルートハンドラをキャッチするためであることがわかりました。
routes.MapRoute(
"Default",
"{controller}/{action}",
new { controller = "Home", action = "Index" }
);
非同期ルートハンドラーを処理するために追加したカスタムルートではなく、リクエストを取得しました。おそらく、カスタムルート定義で.mvcを使用して、同期キャッチオールではなく使用されるように区別を作成しました。
過去にこれを実行しようとしましたが、ビューをレンダリングして取得すると、すべての非同期タスクが終了します。または、非同期タスクは終了しますが、ビューはレンダリングされません。
元のMVCコードに基づいてRouteCollectionExtensionsを作成しました。 AsyncMvcHandlerには、ProcessMethodの空のメソッド(例外なし)がありました。