Merge pull request #249 from pcc/xgetinputfocus
[mono.git] / mcs / class / System.Web.Mvc3 / Mvc / ControllerContext.cs
1 namespace System.Web.Mvc {
2     using System;
3     using System.Diagnostics.CodeAnalysis;
4     using System.Web;
5     using System.Web.Routing;
6     using System.Web.Mvc.Html;
7
8     // Though many of the properties on ControllerContext and its subclassed types are virtual, there are still sealed
9     // properties (like ControllerContext.RequestContext, ActionExecutingContext.Result, etc.). If these properties
10     // were virtual, a mocking framework might override them with incorrect behavior (property getters would return
11     // null, property setters would be no-ops). By sealing these properties, we are forcing them to have the default
12     // "get or store a value" semantics that they were intended to have.
13
14     public class ControllerContext {
15
16         private HttpContextBase _httpContext;
17         private RequestContext _requestContext;
18         private RouteData _routeData;
19
20         internal const string PARENT_ACTION_VIEWCONTEXT = "ParentActionViewContext";
21
22         // parameterless constructor used for mocking
23         public ControllerContext() {
24         }
25
26         // copy constructor - allows for subclassed types to take an existing ControllerContext as a parameter
27         // and we'll automatically set the appropriate properties
28         [SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors", Justification = "The virtual property setters are only to support mocking frameworks, in which case this constructor shouldn't be called anyway.")]
29         protected ControllerContext(ControllerContext controllerContext) {
30             if (controllerContext == null) {
31                 throw new ArgumentNullException("controllerContext");
32             }
33
34             Controller = controllerContext.Controller;
35             RequestContext = controllerContext.RequestContext;
36         }
37
38         public ControllerContext(HttpContextBase httpContext, RouteData routeData, ControllerBase controller)
39             : this(new RequestContext(httpContext, routeData), controller) {
40         }
41
42         [SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors", Justification = "The virtual property setters are only to support mocking frameworks, in which case this constructor shouldn't be called anyway.")]
43         public ControllerContext(RequestContext requestContext, ControllerBase controller) {
44             if (requestContext == null) {
45                 throw new ArgumentNullException("requestContext");
46             }
47             if (controller == null) {
48                 throw new ArgumentNullException("controller");
49             }
50
51             RequestContext = requestContext;
52             Controller = controller;
53         }
54
55         public virtual ControllerBase Controller {
56             get;
57             set;
58         }
59
60         public virtual HttpContextBase HttpContext {
61             get {
62                 if (_httpContext == null) {
63                     _httpContext = (_requestContext != null) ? _requestContext.HttpContext : new EmptyHttpContext();
64                 }
65                 return _httpContext;
66             }
67             set {
68                 _httpContext = value;
69             }
70         }
71
72         public virtual bool IsChildAction {
73             get {
74                 RouteData routeData = RouteData;
75                 if (routeData == null) {
76                     return false;
77                 }
78                 return routeData.DataTokens.ContainsKey(PARENT_ACTION_VIEWCONTEXT);
79             }
80         }
81
82         public ViewContext ParentActionViewContext {
83             get {
84                 return RouteData.DataTokens[PARENT_ACTION_VIEWCONTEXT] as ViewContext;
85             }
86         }
87
88         public RequestContext RequestContext {
89             get {
90                 if (_requestContext == null) {
91                     // still need explicit calls to constructors since the property getters are virtual and might return null
92                     HttpContextBase httpContext = HttpContext ?? new EmptyHttpContext();
93                     RouteData routeData = RouteData ?? new RouteData();
94
95                     _requestContext = new RequestContext(httpContext, routeData);
96                 }
97                 return _requestContext;
98             }
99             set {
100                 _requestContext = value;
101             }
102         }
103
104         public virtual RouteData RouteData {
105             get {
106                 if (_routeData == null) {
107                     _routeData = (_requestContext != null) ? _requestContext.RouteData : new RouteData();
108                 }
109                 return _routeData;
110             }
111             set {
112                 _routeData = value;
113             }
114         }
115
116         private sealed class EmptyHttpContext : HttpContextBase {
117         }
118
119     }
120 }