1 namespace System.Web.Mvc {
3 using System.Diagnostics.CodeAnalysis;
5 using System.Web.Routing;
6 using System.Web.Mvc.Html;
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.
14 public class ControllerContext {
16 private HttpContextBase _httpContext;
17 private RequestContext _requestContext;
18 private RouteData _routeData;
20 internal const string PARENT_ACTION_VIEWCONTEXT = "ParentActionViewContext";
22 // parameterless constructor used for mocking
23 public ControllerContext() {
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");
34 Controller = controllerContext.Controller;
35 RequestContext = controllerContext.RequestContext;
38 public ControllerContext(HttpContextBase httpContext, RouteData routeData, ControllerBase controller)
39 : this(new RequestContext(httpContext, routeData), controller) {
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");
47 if (controller == null) {
48 throw new ArgumentNullException("controller");
51 RequestContext = requestContext;
52 Controller = controller;
55 public virtual ControllerBase Controller {
60 public virtual HttpContextBase HttpContext {
62 if (_httpContext == null) {
63 _httpContext = (_requestContext != null) ? _requestContext.HttpContext : new EmptyHttpContext();
72 public virtual bool IsChildAction {
74 RouteData routeData = RouteData;
75 if (routeData == null) {
78 return routeData.DataTokens.ContainsKey(PARENT_ACTION_VIEWCONTEXT);
82 public ViewContext ParentActionViewContext {
84 return RouteData.DataTokens[PARENT_ACTION_VIEWCONTEXT] as ViewContext;
88 public RequestContext RequestContext {
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();
95 _requestContext = new RequestContext(httpContext, routeData);
97 return _requestContext;
100 _requestContext = value;
104 public virtual RouteData RouteData {
106 if (_routeData == null) {
107 _routeData = (_requestContext != null) ? _requestContext.RouteData : new RouteData();
116 private sealed class EmptyHttpContext : HttpContextBase {