New tests.
[mono.git] / mcs / class / System.Web.Mvc2 / System.Web.Mvc / ReflectedActionDescriptor.cs
1 /* ****************************************************************************\r
2  *\r
3  * Copyright (c) Microsoft Corporation. All rights reserved.\r
4  *\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
8  *\r
9  * You must not remove this notice, or any other, from this software.\r
10  *\r
11  * ***************************************************************************/\r
12 \r
13 namespace System.Web.Mvc {\r
14     using System;\r
15     using System.Collections.Generic;\r
16     using System.Linq;\r
17     using System.Reflection;\r
18     using System.Web.Mvc.Resources;\r
19 \r
20     public class ReflectedActionDescriptor : ActionDescriptor {\r
21 \r
22         private readonly string _actionName;\r
23         private readonly ControllerDescriptor _controllerDescriptor;\r
24         private ParameterDescriptor[] _parametersCache;\r
25 \r
26         public ReflectedActionDescriptor(MethodInfo methodInfo, string actionName, ControllerDescriptor controllerDescriptor)\r
27             : this(methodInfo, actionName, controllerDescriptor, true /* validateMethod */) {\r
28         }\r
29 \r
30         internal ReflectedActionDescriptor(MethodInfo methodInfo, string actionName, ControllerDescriptor controllerDescriptor, bool validateMethod) {\r
31             if (methodInfo == null) {\r
32                 throw new ArgumentNullException("methodInfo");\r
33             }\r
34             if (String.IsNullOrEmpty(actionName)) {\r
35                 throw new ArgumentException(MvcResources.Common_NullOrEmpty, "actionName");\r
36             }\r
37             if (controllerDescriptor == null) {\r
38                 throw new ArgumentNullException("controllerDescriptor");\r
39             }\r
40 \r
41             if (validateMethod) {\r
42                 string failedMessage = VerifyActionMethodIsCallable(methodInfo);\r
43                 if (failedMessage != null) {\r
44                     throw new ArgumentException(failedMessage, "methodInfo");\r
45                 }\r
46             }\r
47 \r
48             MethodInfo = methodInfo;\r
49             _actionName = actionName;\r
50             _controllerDescriptor = controllerDescriptor;\r
51         }\r
52 \r
53         public override string ActionName {\r
54             get {\r
55                 return _actionName;\r
56             }\r
57         }\r
58 \r
59         public override ControllerDescriptor ControllerDescriptor {\r
60             get {\r
61                 return _controllerDescriptor;\r
62             }\r
63         }\r
64 \r
65         public MethodInfo MethodInfo {\r
66             get;\r
67             private set;\r
68         }\r
69 \r
70         public override object Execute(ControllerContext controllerContext, IDictionary<string, object> parameters) {\r
71             if (controllerContext == null) {\r
72                 throw new ArgumentNullException("controllerContext");\r
73             }\r
74             if (parameters == null) {\r
75                 throw new ArgumentNullException("parameters");\r
76             }\r
77 \r
78             ParameterInfo[] parameterInfos = MethodInfo.GetParameters();\r
79             var rawParameterValues = from parameterInfo in parameterInfos\r
80                                      select ExtractParameterFromDictionary(parameterInfo, parameters, MethodInfo);\r
81             object[] parametersArray = rawParameterValues.ToArray();\r
82 \r
83             ActionMethodDispatcher dispatcher = DispatcherCache.GetDispatcher(MethodInfo);\r
84             object actionReturnValue = dispatcher.Execute(controllerContext.Controller, parametersArray);\r
85             return actionReturnValue;\r
86         }\r
87 \r
88         public override object[] GetCustomAttributes(bool inherit) {\r
89             return MethodInfo.GetCustomAttributes(inherit);\r
90         }\r
91 \r
92         public override object[] GetCustomAttributes(Type attributeType, bool inherit) {\r
93             return MethodInfo.GetCustomAttributes(attributeType, inherit);\r
94         }\r
95 \r
96         public override FilterInfo GetFilters() {\r
97             return GetFilters(MethodInfo);\r
98         }\r
99 \r
100         public override ParameterDescriptor[] GetParameters() {\r
101             ParameterDescriptor[] parameters = LazilyFetchParametersCollection();\r
102 \r
103             // need to clone array so that user modifications aren't accidentally stored\r
104             return (ParameterDescriptor[])parameters.Clone();\r
105         }\r
106 \r
107         public override ICollection<ActionSelector> GetSelectors() {\r
108             ActionMethodSelectorAttribute[] attrs = (ActionMethodSelectorAttribute[])MethodInfo.GetCustomAttributes(typeof(ActionMethodSelectorAttribute), true /* inherit */);\r
109             ActionSelector[] selectors = Array.ConvertAll(attrs, attr => (ActionSelector)(controllerContext => attr.IsValidForRequest(controllerContext, MethodInfo)));\r
110             return selectors;\r
111         }\r
112 \r
113         public override bool IsDefined(Type attributeType, bool inherit) {\r
114             return MethodInfo.IsDefined(attributeType, inherit);\r
115         }\r
116 \r
117         private ParameterDescriptor[] LazilyFetchParametersCollection() {\r
118             return DescriptorUtil.LazilyFetchOrCreateDescriptors<ParameterInfo, ParameterDescriptor>(\r
119                 ref _parametersCache /* cacheLocation */,\r
120                 MethodInfo.GetParameters /* initializer */,\r
121                 parameterInfo => new ReflectedParameterDescriptor(parameterInfo, this) /* converter */);\r
122         }\r
123 \r
124         internal static ReflectedActionDescriptor TryCreateDescriptor(MethodInfo methodInfo, string name, ControllerDescriptor controllerDescriptor) {\r
125             ReflectedActionDescriptor descriptor = new ReflectedActionDescriptor(methodInfo, name, controllerDescriptor, false /* validateMethod */);\r
126             string failedMessage = VerifyActionMethodIsCallable(methodInfo);\r
127             return (failedMessage == null) ? descriptor : null;\r
128         }\r
129 \r
130     }\r
131 }\r