1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Web.Mvc.Async;
using System.Web.Routing;
using System.Web.SessionState;
namespace System.Web.Mvc
{
public class MvcHttpHandler : UrlRoutingHandler, IHttpAsyncHandler, IRequiresSessionState
{
private static readonly object _processRequestTag = new object();
protected virtual IAsyncResult BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, object state)
{
HttpContextBase httpContextBase = new HttpContextWrapper(httpContext);
return BeginProcessRequest(httpContextBase, callback, state);
}
protected internal virtual IAsyncResult BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, object state)
{
IHttpHandler httpHandler = GetHttpHandler(httpContext);
IHttpAsyncHandler httpAsyncHandler = httpHandler as IHttpAsyncHandler;
if (httpAsyncHandler != null)
{
// asynchronous handler
BeginInvokeDelegate beginDelegate = delegate(AsyncCallback asyncCallback, object asyncState)
{
return httpAsyncHandler.BeginProcessRequest(HttpContext.Current, asyncCallback, asyncState);
};
EndInvokeDelegate endDelegate = delegate(IAsyncResult asyncResult)
{
httpAsyncHandler.EndProcessRequest(asyncResult);
};
return AsyncResultWrapper.Begin(callback, state, beginDelegate, endDelegate, _processRequestTag);
}
else
{
// synchronous handler
Action action = delegate
{
httpHandler.ProcessRequest(HttpContext.Current);
};
return AsyncResultWrapper.BeginSynchronous(callback, state, action, _processRequestTag);
}
}
protected internal virtual void EndProcessRequest(IAsyncResult asyncResult)
{
AsyncResultWrapper.End(asyncResult, _processRequestTag);
}
private static IHttpHandler GetHttpHandler(HttpContextBase httpContext)
{
DummyHttpHandler dummyHandler = new DummyHttpHandler();
dummyHandler.PublicProcessRequest(httpContext);
return dummyHandler.HttpHandler;
}
// synchronous code
protected override void VerifyAndProcessRequest(IHttpHandler httpHandler, HttpContextBase httpContext)
{
if (httpHandler == null)
{
throw new ArgumentNullException("httpHandler");
}
httpHandler.ProcessRequest(HttpContext.Current);
}
#region IHttpAsyncHandler Members
IAsyncResult IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
{
return BeginProcessRequest(context, cb, extraData);
}
void IHttpAsyncHandler.EndProcessRequest(IAsyncResult result)
{
EndProcessRequest(result);
}
#endregion
// Since UrlRoutingHandler.ProcessRequest() does the heavy lifting of looking at the RouteCollection for
// a matching route, we need to call into it. However, that method is also responsible for kicking off
// the synchronous request, and we can't allow it to do that. The purpose of this dummy class is to run
// only the lookup portion of UrlRoutingHandler.ProcessRequest(), then intercept the handler it returns
// and execute it asynchronously.
private sealed class DummyHttpHandler : UrlRoutingHandler
{
public IHttpHandler HttpHandler;
public void PublicProcessRequest(HttpContextBase httpContext)
{
ProcessRequest(httpContext);
}
protected override void VerifyAndProcessRequest(IHttpHandler httpHandler, HttpContextBase httpContext)
{
// don't process the request, just store a reference to it
HttpHandler = httpHandler;
}
}
}
}
|