Merge pull request #249 from pcc/xgetinputfocus
[mono.git] / mcs / class / System.Web.Mvc3 / Mvc / Html / ChildActionExtensions.cs
1 namespace System.Web.Mvc.Html {
2     using System.Collections.Generic;
3     using System.Globalization;
4     using System.IO;
5     using System.Linq;
6     using System.Web.Mvc.Resources;
7     using System.Web.Routing;
8
9     public static class ChildActionExtensions {
10
11         // Action
12
13         public static MvcHtmlString Action(this HtmlHelper htmlHelper, string actionName) {
14             return Action(htmlHelper, actionName, null /* controllerName */, null /* routeValues */);
15         }
16
17         public static MvcHtmlString Action(this HtmlHelper htmlHelper, string actionName, object routeValues) {
18             return Action(htmlHelper, actionName, null /* controllerName */, new RouteValueDictionary(routeValues));
19         }
20
21         public static MvcHtmlString Action(this HtmlHelper htmlHelper, string actionName, RouteValueDictionary routeValues) {
22             return Action(htmlHelper, actionName, null /* controllerName */, routeValues);
23         }
24
25         public static MvcHtmlString Action(this HtmlHelper htmlHelper, string actionName, string controllerName) {
26             return Action(htmlHelper, actionName, controllerName, null /* routeValues */);
27         }
28
29         public static MvcHtmlString Action(this HtmlHelper htmlHelper, string actionName, string controllerName, object routeValues) {
30             return Action(htmlHelper, actionName, controllerName, new RouteValueDictionary(routeValues));
31         }
32
33         public static MvcHtmlString Action(this HtmlHelper htmlHelper, string actionName, string controllerName, RouteValueDictionary routeValues) {
34             using (StringWriter writer = new StringWriter(CultureInfo.CurrentCulture)) {
35                 ActionHelper(htmlHelper, actionName, controllerName, routeValues, writer);
36                 return MvcHtmlString.Create(writer.ToString());
37             }
38         }
39
40         // RenderAction
41
42         public static void RenderAction(this HtmlHelper htmlHelper, string actionName) {
43             RenderAction(htmlHelper, actionName, null /* controllerName */, null /* routeValues */);
44         }
45
46         public static void RenderAction(this HtmlHelper htmlHelper, string actionName, object routeValues) {
47             RenderAction(htmlHelper, actionName, null /* controllerName */, new RouteValueDictionary(routeValues));
48         }
49
50         public static void RenderAction(this HtmlHelper htmlHelper, string actionName, RouteValueDictionary routeValues) {
51             RenderAction(htmlHelper, actionName, null /* controllerName */, routeValues);
52         }
53
54         public static void RenderAction(this HtmlHelper htmlHelper, string actionName, string controllerName) {
55             RenderAction(htmlHelper, actionName, controllerName, null /* routeValues */);
56         }
57
58         public static void RenderAction(this HtmlHelper htmlHelper, string actionName, string controllerName, object routeValues) {
59             RenderAction(htmlHelper, actionName, controllerName, new RouteValueDictionary(routeValues));
60         }
61
62         public static void RenderAction(this HtmlHelper htmlHelper, string actionName, string controllerName, RouteValueDictionary routeValues) {
63             ActionHelper(htmlHelper, actionName, controllerName, routeValues, htmlHelper.ViewContext.Writer);
64         }
65
66         // Helpers
67
68         internal static void ActionHelper(HtmlHelper htmlHelper, string actionName, string controllerName, RouteValueDictionary routeValues, TextWriter textWriter) {
69             if (htmlHelper == null) {
70                 throw new ArgumentNullException("htmlHelper");
71             }
72             if (String.IsNullOrEmpty(actionName)) {
73                 throw new ArgumentException(MvcResources.Common_NullOrEmpty, "actionName");
74             }
75
76             RouteValueDictionary additionalRouteValues = routeValues;
77             routeValues = MergeDictionaries(routeValues, htmlHelper.ViewContext.RouteData.Values);
78                      
79             routeValues["action"] = actionName;
80             if (!String.IsNullOrEmpty(controllerName)) {
81                 routeValues["controller"] = controllerName;
82             }
83
84             bool usingAreas;
85             VirtualPathData vpd = htmlHelper.RouteCollection.GetVirtualPathForArea(htmlHelper.ViewContext.RequestContext, null /* name */, routeValues, out usingAreas);
86             if (vpd == null) {
87                 throw new InvalidOperationException(MvcResources.Common_NoRouteMatched);
88             }
89    
90             if (usingAreas) {
91                 routeValues.Remove("area");
92                 if (additionalRouteValues != null) {
93                     additionalRouteValues.Remove("area");
94                 }
95             }
96
97             if (additionalRouteValues != null) {
98                 routeValues[ChildActionValueProvider.ChildActionValuesKey] = new DictionaryValueProvider<object>(additionalRouteValues, CultureInfo.InvariantCulture);
99             }
100
101             RouteData routeData = CreateRouteData(vpd.Route, routeValues, vpd.DataTokens, htmlHelper.ViewContext);
102             HttpContextBase httpContext = htmlHelper.ViewContext.HttpContext;
103             RequestContext requestContext = new RequestContext(httpContext, routeData);
104             ChildActionMvcHandler handler = new ChildActionMvcHandler(requestContext);
105             httpContext.Server.Execute(HttpHandlerUtil.WrapForServerExecute(handler), textWriter, true /* preserveForm */);
106         }
107
108         private static RouteData CreateRouteData(RouteBase route, RouteValueDictionary routeValues, RouteValueDictionary dataTokens, ViewContext parentViewContext) {
109             RouteData routeData = new RouteData();
110
111             foreach (KeyValuePair<string, object> kvp in routeValues) {
112                 routeData.Values.Add(kvp.Key, kvp.Value);
113             }
114
115             foreach (KeyValuePair<string, object> kvp in dataTokens) {
116                 routeData.DataTokens.Add(kvp.Key, kvp.Value);
117             }
118
119             routeData.Route = route;
120             routeData.DataTokens[ControllerContext.PARENT_ACTION_VIEWCONTEXT] = parentViewContext;
121             return routeData;
122         }
123
124         private static RouteValueDictionary MergeDictionaries(params RouteValueDictionary[] dictionaries) {
125             // Merge existing route values with the user provided values
126             var result = new RouteValueDictionary();
127
128             foreach (RouteValueDictionary dictionary in dictionaries.Where(d => d != null)) {
129                 foreach (KeyValuePair<string, object> kvp in dictionary) {
130                     if (!result.ContainsKey(kvp.Key)) {
131                         result.Add(kvp.Key, kvp.Value);
132                     }
133                 }
134             }
135
136             return result;
137         }
138
139         internal class ChildActionMvcHandler : MvcHandler {
140             public ChildActionMvcHandler(RequestContext context)
141                 : base(context) {
142             }
143
144             protected internal override void AddVersionHeader(HttpContextBase httpContext) {
145                 // No version header for child actions
146             }
147         }
148     }
149 }