Merge pull request #249 from pcc/xgetinputfocus
[mono.git] / mcs / class / System.Web.Mvc3 / Mvc / AsyncController.cs
1 namespace System.Web.Mvc {
2     using System;
3     using System.Web.Mvc.Async;
4     using System.Web.Routing;
5
6     public abstract class AsyncController : Controller, IAsyncManagerContainer, IAsyncController {
7
8         private static readonly object _executeTag = new object();
9         private static readonly object _executeCoreTag = new object();
10
11         private readonly AsyncManager _asyncManager = new AsyncManager();
12
13         public AsyncManager AsyncManager {
14             get {
15                 return _asyncManager;
16             }
17         }
18
19         protected virtual IAsyncResult BeginExecute(RequestContext requestContext, AsyncCallback callback, object state) {
20             if (requestContext == null) {
21                 throw new ArgumentNullException("requestContext");
22             }
23
24             VerifyExecuteCalledOnce();
25             Initialize(requestContext);
26             return AsyncResultWrapper.Begin(callback, state, BeginExecuteCore, EndExecuteCore, _executeTag);
27         }
28
29         protected virtual IAsyncResult BeginExecuteCore(AsyncCallback callback, object state) {
30             // If code in this method needs to be updated, please also check the ExecuteCore() method
31             // of Controller to see if that code also must be updated.
32
33             PossiblyLoadTempData();
34             try {
35                 string actionName = RouteData.GetRequiredString("action");
36                 IActionInvoker invoker = ActionInvoker;
37                 IAsyncActionInvoker asyncInvoker = invoker as IAsyncActionInvoker;
38                 if (asyncInvoker != null) {
39                     // asynchronous invocation
40                     BeginInvokeDelegate beginDelegate = delegate(AsyncCallback asyncCallback, object asyncState) {
41                         return asyncInvoker.BeginInvokeAction(ControllerContext, actionName, asyncCallback, asyncState);
42                     };
43
44                     EndInvokeDelegate endDelegate = delegate(IAsyncResult asyncResult) {
45                         if (!asyncInvoker.EndInvokeAction(asyncResult)) {
46                             HandleUnknownAction(actionName);
47                         }
48                     };
49
50                     return AsyncResultWrapper.Begin(callback, state, beginDelegate, endDelegate, _executeCoreTag);
51                 }
52                 else {
53                     // synchronous invocation
54                     Action action = () => {
55                         if (!invoker.InvokeAction(ControllerContext, actionName)) {
56                             HandleUnknownAction(actionName);
57                         }
58                     };
59                     return AsyncResultWrapper.BeginSynchronous(callback, state, action, _executeCoreTag);
60                 }
61             }
62             catch {
63                 PossiblySaveTempData();
64                 throw;
65             }
66         }
67
68         protected override IActionInvoker CreateActionInvoker() {
69             return new AsyncControllerActionInvoker();
70         }
71
72         protected virtual void EndExecute(IAsyncResult asyncResult) {
73             AsyncResultWrapper.End(asyncResult, _executeTag);
74         }
75
76         protected virtual void EndExecuteCore(IAsyncResult asyncResult) {
77             // If code in this method needs to be updated, please also check the ExecuteCore() method
78             // of Controller to see if that code also must be updated.
79
80             try {
81                 AsyncResultWrapper.End(asyncResult, _executeCoreTag);
82             }
83             finally {
84                 PossiblySaveTempData();
85             }
86         }
87
88         #region IAsyncController Members
89         IAsyncResult IAsyncController.BeginExecute(RequestContext requestContext, AsyncCallback callback, object state) {
90             return BeginExecute(requestContext, callback, state);
91         }
92
93         void IAsyncController.EndExecute(IAsyncResult asyncResult) {
94             EndExecute(asyncResult);
95         }
96         #endregion
97
98     }
99 }