1 /* ****************************************************************************
\r
3 * Copyright (c) Microsoft Corporation. All rights reserved.
\r
5 * This software is subject to the Microsoft Public License (Ms-PL).
\r
6 * A copy of the license can be found in the license.htm file included
\r
7 * in this distribution.
\r
9 * You must not remove this notice, or any other, from this software.
\r
11 * ***************************************************************************/
\r
13 namespace System.Web.Mvc {
\r
15 using System.Diagnostics.CodeAnalysis;
\r
17 using System.Web.Routing;
\r
18 using System.Web.Mvc.Html;
\r
20 // Though many of the properties on ControllerContext and its subclassed types are virtual, there are still sealed
\r
21 // properties (like ControllerContext.RequestContext, ActionExecutingContext.Result, etc.). If these properties
\r
22 // were virtual, a mocking framework might override them with incorrect behavior (property getters would return
\r
23 // null, property setters would be no-ops). By sealing these properties, we are forcing them to have the default
\r
24 // "get or store a value" semantics that they were intended to have.
\r
26 public class ControllerContext {
\r
28 private HttpContextBase _httpContext;
\r
29 private RequestContext _requestContext;
\r
30 private RouteData _routeData;
\r
32 internal const string PARENT_ACTION_VIEWCONTEXT = "ParentActionViewContext";
\r
34 // parameterless constructor used for mocking
\r
35 public ControllerContext() {
\r
38 // copy constructor - allows for subclassed types to take an existing ControllerContext as a parameter
\r
39 // and we'll automatically set the appropriate properties
\r
40 [SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors",
\r
41 Justification = "The virtual property setters are only to support mocking frameworks, in which case this constructor shouldn't be called anyway.")]
\r
42 protected ControllerContext(ControllerContext controllerContext) {
\r
43 if (controllerContext == null) {
\r
44 throw new ArgumentNullException("controllerContext");
\r
47 Controller = controllerContext.Controller;
\r
48 RequestContext = controllerContext.RequestContext;
\r
51 public ControllerContext(HttpContextBase httpContext, RouteData routeData, ControllerBase controller)
\r
52 : this(new RequestContext(httpContext, routeData), controller) {
\r
55 [SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors",
\r
56 Justification = "The virtual property setters are only to support mocking frameworks, in which case this constructor shouldn't be called anyway.")]
\r
57 public ControllerContext(RequestContext requestContext, ControllerBase controller) {
\r
58 if (requestContext == null) {
\r
59 throw new ArgumentNullException("requestContext");
\r
61 if (controller == null) {
\r
62 throw new ArgumentNullException("controller");
\r
65 RequestContext = requestContext;
\r
66 Controller = controller;
\r
69 public virtual ControllerBase Controller {
\r
74 public virtual HttpContextBase HttpContext {
\r
76 if (_httpContext == null) {
\r
77 _httpContext = (_requestContext != null) ? _requestContext.HttpContext : new EmptyHttpContext();
\r
79 return _httpContext;
\r
82 _httpContext = value;
\r
86 public virtual bool IsChildAction {
\r
88 RouteData routeData = RouteData;
\r
89 if (routeData == null) {
\r
92 return routeData.DataTokens.ContainsKey(PARENT_ACTION_VIEWCONTEXT);
\r
96 public ViewContext ParentActionViewContext {
\r
98 return RouteData.DataTokens[PARENT_ACTION_VIEWCONTEXT] as ViewContext;
\r
102 public RequestContext RequestContext {
\r
104 if (_requestContext == null) {
\r
105 // still need explicit calls to constructors since the property getters are virtual and might return null
\r
106 HttpContextBase httpContext = HttpContext ?? new EmptyHttpContext();
\r
107 RouteData routeData = RouteData ?? new RouteData();
\r
109 _requestContext = new RequestContext(httpContext, routeData);
\r
111 return _requestContext;
\r
114 _requestContext = value;
\r
118 public virtual RouteData RouteData {
\r
120 if (_routeData == null) {
\r
121 _routeData = (_requestContext != null) ? _requestContext.RouteData : new RouteData();
\r
126 _routeData = value;
\r
130 private sealed class EmptyHttpContext : HttpContextBase {
\r