New tests.
[mono.git] / mcs / class / System.Web.Mvc2 / System.Web.Mvc / Ajax / AjaxExtensions.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.Ajax {\r
14     using System;\r
15     using System.Collections.Generic;\r
16     using System.ComponentModel;\r
17     using System.Diagnostics.CodeAnalysis;\r
18     using System.Globalization;\r
19     using System.Web;\r
20     using System.Web.Mvc;\r
21     using System.Web.Mvc.Html;\r
22     using System.Web.Mvc.Resources;\r
23     using System.Web.Routing;\r
24 \r
25     public static class AjaxExtensions {\r
26         private const string LinkOnClickFormat = "Sys.Mvc.AsyncHyperlink.handleClick(this, new Sys.UI.DomEvent(event), {0});";\r
27         private const string FormOnClickValue = "Sys.Mvc.AsyncForm.handleClick(this, new Sys.UI.DomEvent(event));";\r
28         private const string FormOnSubmitFormat = "Sys.Mvc.AsyncForm.handleSubmit(this, new Sys.UI.DomEvent(event), {0});";\r
29         private const string _globalizationScript = @"<script type=""text/javascript"" src=""{0}""></script>";\r
30 \r
31         public static MvcHtmlString ActionLink(this AjaxHelper ajaxHelper, string linkText, string actionName, AjaxOptions ajaxOptions) {\r
32             return ActionLink(ajaxHelper, linkText, actionName, (string)null /* controllerName */, ajaxOptions);\r
33         }\r
34 \r
35         public static MvcHtmlString ActionLink(this AjaxHelper ajaxHelper, string linkText, string actionName, object routeValues, AjaxOptions ajaxOptions) {\r
36             return ActionLink(ajaxHelper, linkText, actionName, (string)null /* controllerName */, routeValues, ajaxOptions);\r
37         }\r
38 \r
39         public static MvcHtmlString ActionLink(this AjaxHelper ajaxHelper, string linkText, string actionName, object routeValues, AjaxOptions ajaxOptions, object htmlAttributes) {\r
40             return ActionLink(ajaxHelper, linkText, actionName, (string)null /* controllerName */, routeValues, ajaxOptions, htmlAttributes);\r
41         }\r
42 \r
43         public static MvcHtmlString ActionLink(this AjaxHelper ajaxHelper, string linkText, string actionName, RouteValueDictionary routeValues, AjaxOptions ajaxOptions) {\r
44             return ActionLink(ajaxHelper, linkText, actionName, (string)null /* controllerName */, routeValues, ajaxOptions);\r
45         }\r
46 \r
47         public static MvcHtmlString ActionLink(this AjaxHelper ajaxHelper, string linkText, string actionName, RouteValueDictionary routeValues, AjaxOptions ajaxOptions, IDictionary<string, object> htmlAttributes) {\r
48             return ActionLink(ajaxHelper, linkText, actionName, (string)null /* controllerName */, routeValues, ajaxOptions, htmlAttributes);\r
49         }\r
50 \r
51         public static MvcHtmlString ActionLink(this AjaxHelper ajaxHelper, string linkText, string actionName, string controllerName, AjaxOptions ajaxOptions) {\r
52             return ActionLink(ajaxHelper, linkText, actionName, controllerName, null /* values */, ajaxOptions, null /* htmlAttributes */);\r
53         }\r
54 \r
55         public static MvcHtmlString ActionLink(this AjaxHelper ajaxHelper, string linkText, string actionName, string controllerName, object routeValues, AjaxOptions ajaxOptions) {\r
56             return ActionLink(ajaxHelper, linkText, actionName, controllerName, routeValues, ajaxOptions, null /* htmlAttributes */);\r
57         }\r
58 \r
59         public static MvcHtmlString ActionLink(this AjaxHelper ajaxHelper, string linkText, string actionName, string controllerName, object routeValues, AjaxOptions ajaxOptions, object htmlAttributes) {\r
60             RouteValueDictionary newValues = new RouteValueDictionary(routeValues);\r
61             Dictionary<string, object> newAttributes = ObjectToCaseSensitiveDictionary(htmlAttributes);\r
62             return ActionLink(ajaxHelper, linkText, actionName, controllerName, newValues, ajaxOptions, newAttributes);\r
63         }\r
64 \r
65         public static MvcHtmlString ActionLink(this AjaxHelper ajaxHelper, string linkText, string actionName, string controllerName, RouteValueDictionary routeValues, AjaxOptions ajaxOptions) {\r
66             return ActionLink(ajaxHelper, linkText, actionName, controllerName, routeValues, ajaxOptions, null /* htmlAttributes */);\r
67         }\r
68 \r
69         public static MvcHtmlString ActionLink(this AjaxHelper ajaxHelper, string linkText, string actionName, string controllerName, RouteValueDictionary routeValues, AjaxOptions ajaxOptions, IDictionary<string, object> htmlAttributes) {\r
70             if (String.IsNullOrEmpty(linkText)) {\r
71                 throw new ArgumentException(MvcResources.Common_NullOrEmpty, "linkText");\r
72             }\r
73 \r
74             string targetUrl = UrlHelper.GenerateUrl(null, actionName, controllerName, routeValues, ajaxHelper.RouteCollection, ajaxHelper.ViewContext.RequestContext, true /* includeImplicitMvcValues */);\r
75 \r
76             return MvcHtmlString.Create(GenerateLink(linkText, targetUrl, GetAjaxOptions(ajaxOptions), htmlAttributes));\r
77         }\r
78 \r
79         public static MvcHtmlString ActionLink(this AjaxHelper ajaxHelper, string linkText, string actionName, string controllerName, string protocol, string hostName, string fragment, object routeValues, AjaxOptions ajaxOptions, object htmlAttributes) {\r
80             RouteValueDictionary newValues = new RouteValueDictionary(routeValues);\r
81             Dictionary<string, object> newAttributes = ObjectToCaseSensitiveDictionary(htmlAttributes);\r
82             return ActionLink(ajaxHelper, linkText, actionName, controllerName, protocol, hostName, fragment, newValues, ajaxOptions, newAttributes);\r
83         }\r
84 \r
85         public static MvcHtmlString ActionLink(this AjaxHelper ajaxHelper, string linkText, string actionName, string controllerName, string protocol, string hostName, string fragment, RouteValueDictionary routeValues, AjaxOptions ajaxOptions, IDictionary<string, object> htmlAttributes) {\r
86             if (String.IsNullOrEmpty(linkText)) {\r
87                 throw new ArgumentException(MvcResources.Common_NullOrEmpty, "linkText");\r
88             }\r
89 \r
90             string targetUrl = UrlHelper.GenerateUrl(null /* routeName */, actionName, controllerName, protocol, hostName, fragment, routeValues, ajaxHelper.RouteCollection, ajaxHelper.ViewContext.RequestContext, true /* includeImplicitMvcValues */);\r
91 \r
92             return MvcHtmlString.Create(GenerateLink(linkText, targetUrl, ajaxOptions, htmlAttributes));\r
93         }\r
94 \r
95         public static MvcForm BeginForm(this AjaxHelper ajaxHelper, AjaxOptions ajaxOptions) {\r
96             string formAction = ajaxHelper.ViewContext.HttpContext.Request.RawUrl;\r
97             return FormHelper(ajaxHelper, formAction, ajaxOptions, new RouteValueDictionary());\r
98         }\r
99 \r
100         public static MvcForm BeginForm(this AjaxHelper ajaxHelper, string actionName, AjaxOptions ajaxOptions) {\r
101             return BeginForm(ajaxHelper, actionName, (string)null /* controllerName */, ajaxOptions);\r
102         }\r
103 \r
104         public static MvcForm BeginForm(this AjaxHelper ajaxHelper, string actionName, object routeValues, AjaxOptions ajaxOptions) {\r
105             return BeginForm(ajaxHelper, actionName, (string)null /* controllerName */, routeValues, ajaxOptions);\r
106         }\r
107 \r
108         public static MvcForm BeginForm(this AjaxHelper ajaxHelper, string actionName, object routeValues, AjaxOptions ajaxOptions, object htmlAttributes) {\r
109             return BeginForm(ajaxHelper, actionName, (string)null /* controllerName */, routeValues, ajaxOptions, htmlAttributes);\r
110         }\r
111 \r
112         public static MvcForm BeginForm(this AjaxHelper ajaxHelper, string actionName, RouteValueDictionary routeValues, AjaxOptions ajaxOptions) {\r
113             return BeginForm(ajaxHelper, actionName, (string)null /* controllerName */, routeValues, ajaxOptions);\r
114         }\r
115 \r
116         public static MvcForm BeginForm(this AjaxHelper ajaxHelper, string actionName, RouteValueDictionary routeValues, AjaxOptions ajaxOptions, IDictionary<string, object> htmlAttributes) {\r
117             return BeginForm(ajaxHelper, actionName, (string)null /* controllerName */, routeValues, ajaxOptions, htmlAttributes);\r
118         }\r
119 \r
120         public static MvcForm BeginForm(this AjaxHelper ajaxHelper, string actionName, string controllerName, AjaxOptions ajaxOptions) {\r
121             return BeginForm(ajaxHelper, actionName, controllerName, null /* values */, ajaxOptions, null /* htmlAttributes */);\r
122         }\r
123 \r
124         public static MvcForm BeginForm(this AjaxHelper ajaxHelper, string actionName, string controllerName, object routeValues, AjaxOptions ajaxOptions) {\r
125             return BeginForm(ajaxHelper, actionName, controllerName, routeValues, ajaxOptions, null /* htmlAttributes */);\r
126         }\r
127 \r
128         public static MvcForm BeginForm(this AjaxHelper ajaxHelper, string actionName, string controllerName, object routeValues, AjaxOptions ajaxOptions, object htmlAttributes) {\r
129             RouteValueDictionary newValues = new RouteValueDictionary(routeValues);\r
130             Dictionary<string, object> newAttributes = ObjectToCaseSensitiveDictionary(htmlAttributes);\r
131             return BeginForm(ajaxHelper, actionName, controllerName, newValues, ajaxOptions, newAttributes);\r
132         }\r
133 \r
134         public static MvcForm BeginForm(this AjaxHelper ajaxHelper, string actionName, string controllerName, RouteValueDictionary routeValues, AjaxOptions ajaxOptions) {\r
135             return BeginForm(ajaxHelper, actionName, controllerName, routeValues, ajaxOptions, null /* htmlAttributes */);\r
136         }\r
137 \r
138         public static MvcForm BeginForm(this AjaxHelper ajaxHelper, string actionName, string controllerName, RouteValueDictionary routeValues, AjaxOptions ajaxOptions, IDictionary<string, object> htmlAttributes) {\r
139             // get target URL\r
140             string formAction = UrlHelper.GenerateUrl(null, actionName, controllerName, routeValues ?? new RouteValueDictionary(), ajaxHelper.RouteCollection, ajaxHelper.ViewContext.RequestContext, true /* includeImplicitMvcValues */);\r
141             return FormHelper(ajaxHelper, formAction, ajaxOptions, htmlAttributes);\r
142         }\r
143 \r
144         public static MvcForm BeginRouteForm(this AjaxHelper ajaxHelper, string routeName, AjaxOptions ajaxOptions) {\r
145             return BeginRouteForm(ajaxHelper, routeName, null /* routeValues */, ajaxOptions, null /* htmlAttributes */);\r
146         }\r
147 \r
148         public static MvcForm BeginRouteForm(this AjaxHelper ajaxHelper, string routeName, object routeValues, AjaxOptions ajaxOptions) {\r
149             return BeginRouteForm(ajaxHelper, routeName, (object)routeValues, ajaxOptions, null /* htmlAttributes */);\r
150         }\r
151 \r
152         public static MvcForm BeginRouteForm(this AjaxHelper ajaxHelper, string routeName, object routeValues, AjaxOptions ajaxOptions, object htmlAttributes) {\r
153             Dictionary<string, object> newAttributes = ObjectToCaseSensitiveDictionary(htmlAttributes);\r
154             return BeginRouteForm(ajaxHelper, routeName, new RouteValueDictionary(routeValues), ajaxOptions, newAttributes);\r
155         }\r
156 \r
157         public static MvcForm BeginRouteForm(this AjaxHelper ajaxHelper, string routeName, RouteValueDictionary routeValues, AjaxOptions ajaxOptions) {\r
158             return BeginRouteForm(ajaxHelper, routeName, routeValues, ajaxOptions, null /* htmlAttributes */);\r
159         }\r
160 \r
161         public static MvcForm BeginRouteForm(this AjaxHelper ajaxHelper, string routeName, RouteValueDictionary routeValues, AjaxOptions ajaxOptions, IDictionary<string, object> htmlAttributes) {\r
162             string formAction = UrlHelper.GenerateUrl(routeName, null /* actionName */, null /* controllerName */, routeValues ?? new RouteValueDictionary(), ajaxHelper.RouteCollection, ajaxHelper.ViewContext.RequestContext, false /* includeImplicitMvcValues */);\r
163             return FormHelper(ajaxHelper, formAction, ajaxOptions, htmlAttributes);\r
164         }\r
165 \r
166         private static MvcForm FormHelper(this AjaxHelper ajaxHelper, string formAction, AjaxOptions ajaxOptions, IDictionary<string, object> htmlAttributes) {\r
167             TagBuilder builder = new TagBuilder("form");\r
168             builder.MergeAttributes(htmlAttributes);\r
169             builder.MergeAttribute("action", formAction);\r
170             builder.MergeAttribute("method", "post");\r
171             builder.MergeAttribute("onclick", FormOnClickValue);\r
172             builder.MergeAttribute("onsubmit", GenerateAjaxScript(GetAjaxOptions(ajaxOptions), FormOnSubmitFormat));\r
173 \r
174             if (ajaxHelper.ViewContext.ClientValidationEnabled) {\r
175                 // forms must have an ID for client validation\r
176                 builder.GenerateId(ajaxHelper.ViewContext.FormIdGenerator());\r
177             }\r
178 \r
179             ajaxHelper.ViewContext.Writer.Write(builder.ToString(TagRenderMode.StartTag));\r
180             MvcForm theForm = new MvcForm(ajaxHelper.ViewContext);\r
181 \r
182             if (ajaxHelper.ViewContext.ClientValidationEnabled) {\r
183                 ajaxHelper.ViewContext.FormContext.FormId = builder.Attributes["id"];\r
184             }\r
185 \r
186             return theForm;\r
187         }\r
188 \r
189         public static MvcHtmlString GlobalizationScript(this AjaxHelper ajaxHelper) {\r
190             return GlobalizationScript(ajaxHelper, CultureInfo.CurrentCulture);\r
191         }\r
192 \r
193         [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "ajaxHelper",\r
194             Justification = "This is an extension method")]\r
195         public static MvcHtmlString GlobalizationScript(this AjaxHelper ajaxHelper, CultureInfo cultureInfo) {\r
196             return GlobalizationScriptHelper(AjaxHelper.GlobalizationScriptPath, cultureInfo);\r
197         }\r
198 \r
199         private static MvcHtmlString GlobalizationScriptHelper(string scriptPath, CultureInfo cultureInfo) {\r
200             if (cultureInfo == null) {\r
201                 throw new ArgumentNullException("cultureInfo");\r
202             }\r
203 \r
204             string src = VirtualPathUtility.AppendTrailingSlash(scriptPath) + cultureInfo.Name + ".js";\r
205             string scriptWithCorrectNewLines = _globalizationScript.Replace("\r\n", Environment.NewLine);\r
206             string formatted = String.Format(CultureInfo.InvariantCulture, scriptWithCorrectNewLines, src);\r
207 \r
208             return MvcHtmlString.Create(formatted);\r
209         }\r
210 \r
211         public static MvcHtmlString RouteLink(this AjaxHelper ajaxHelper, string linkText, object routeValues, AjaxOptions ajaxOptions) {\r
212             return RouteLink(ajaxHelper, linkText, null /* routeName */, new RouteValueDictionary(routeValues), ajaxOptions,\r
213                              new Dictionary<string, object>());\r
214         }\r
215 \r
216         public static MvcHtmlString RouteLink(this AjaxHelper ajaxHelper, string linkText, object routeValues, AjaxOptions ajaxOptions, object htmlAttributes) {\r
217             return RouteLink(ajaxHelper, linkText, null /* routeName */, new RouteValueDictionary(routeValues), ajaxOptions,\r
218                              ObjectToCaseSensitiveDictionary(htmlAttributes));\r
219         }\r
220 \r
221         public static MvcHtmlString RouteLink(this AjaxHelper ajaxHelper, string linkText, RouteValueDictionary routeValues, AjaxOptions ajaxOptions) {\r
222             return RouteLink(ajaxHelper, linkText, null /* routeName */, routeValues, ajaxOptions,\r
223                              new Dictionary<string, object>());\r
224         }\r
225 \r
226         public static MvcHtmlString RouteLink(this AjaxHelper ajaxHelper, string linkText, RouteValueDictionary routeValues, AjaxOptions ajaxOptions, IDictionary<string, object> htmlAttributes) {\r
227             return RouteLink(ajaxHelper, linkText, null /* routeName */, routeValues, ajaxOptions, htmlAttributes);\r
228         }\r
229 \r
230         public static MvcHtmlString RouteLink(this AjaxHelper ajaxHelper, string linkText, string routeName, AjaxOptions ajaxOptions) {\r
231             return RouteLink(ajaxHelper, linkText, routeName, new RouteValueDictionary(), ajaxOptions,\r
232                              new Dictionary<string, object>());\r
233         }\r
234 \r
235         public static MvcHtmlString RouteLink(this AjaxHelper ajaxHelper, string linkText, string routeName, AjaxOptions ajaxOptions, object htmlAttributes) {\r
236             return RouteLink(ajaxHelper, linkText, routeName, new RouteValueDictionary(), ajaxOptions, ObjectToCaseSensitiveDictionary(htmlAttributes));\r
237         }\r
238 \r
239         public static MvcHtmlString RouteLink(this AjaxHelper ajaxHelper, string linkText, string routeName, AjaxOptions ajaxOptions, IDictionary<string, object> htmlAttributes) {\r
240             return RouteLink(ajaxHelper, linkText, routeName, new RouteValueDictionary(), ajaxOptions, htmlAttributes);\r
241         }\r
242 \r
243         public static MvcHtmlString RouteLink(this AjaxHelper ajaxHelper, string linkText, string routeName, object routeValues, AjaxOptions ajaxOptions) {\r
244             return RouteLink(ajaxHelper, linkText, routeName, new RouteValueDictionary(routeValues), ajaxOptions,\r
245                              new Dictionary<string, object>());\r
246         }\r
247 \r
248         public static MvcHtmlString RouteLink(this AjaxHelper ajaxHelper, string linkText, string routeName, object routeValues, AjaxOptions ajaxOptions, object htmlAttributes) {\r
249             return RouteLink(ajaxHelper, linkText, routeName, new RouteValueDictionary(routeValues), ajaxOptions,\r
250                              ObjectToCaseSensitiveDictionary(htmlAttributes));\r
251         }\r
252 \r
253         public static MvcHtmlString RouteLink(this AjaxHelper ajaxHelper, string linkText, string routeName, RouteValueDictionary routeValues, AjaxOptions ajaxOptions) {\r
254             return RouteLink(ajaxHelper, linkText, routeName, routeValues, ajaxOptions, new Dictionary<string, object>());\r
255         }\r
256 \r
257         public static MvcHtmlString RouteLink(this AjaxHelper ajaxHelper, string linkText, string routeName, RouteValueDictionary routeValues, AjaxOptions ajaxOptions, IDictionary<string, object> htmlAttributes) {\r
258             if (String.IsNullOrEmpty(linkText)) {\r
259                 throw new ArgumentException(MvcResources.Common_NullOrEmpty, "linkText");\r
260             }\r
261 \r
262             string targetUrl = UrlHelper.GenerateUrl(routeName, null /* actionName */, null /* controllerName */, routeValues ?? new RouteValueDictionary(), ajaxHelper.RouteCollection, ajaxHelper.ViewContext.RequestContext, false /* includeImplicitMvcValues */);\r
263 \r
264             return MvcHtmlString.Create(GenerateLink(linkText, targetUrl, GetAjaxOptions(ajaxOptions), htmlAttributes));\r
265         }\r
266 \r
267         public static MvcHtmlString RouteLink(this AjaxHelper ajaxHelper, string linkText, string routeName, string protocol, string hostName, string fragment, RouteValueDictionary routeValues, AjaxOptions ajaxOptions, IDictionary<string, object> htmlAttributes) {\r
268             if (String.IsNullOrEmpty(linkText)) {\r
269                 throw new ArgumentException(MvcResources.Common_NullOrEmpty, "linkText");\r
270             }\r
271 \r
272             string targetUrl = UrlHelper.GenerateUrl(routeName, null /* actionName */, null /* controllerName */, protocol, hostName, fragment, routeValues ?? new RouteValueDictionary(), ajaxHelper.RouteCollection, ajaxHelper.ViewContext.RequestContext, false /* includeImplicitMvcValues */);\r
273 \r
274             return MvcHtmlString.Create(GenerateLink(linkText, targetUrl, GetAjaxOptions(ajaxOptions), htmlAttributes));\r
275         }\r
276 \r
277         internal static string InsertionModeToString(InsertionMode insertionMode) {\r
278             switch (insertionMode) {\r
279                 case InsertionMode.Replace:\r
280                     return "Sys.Mvc.InsertionMode.replace";\r
281                 case InsertionMode.InsertBefore:\r
282                     return "Sys.Mvc.InsertionMode.insertBefore";\r
283                 case InsertionMode.InsertAfter:\r
284                     return "Sys.Mvc.InsertionMode.insertAfter";\r
285                 default:\r
286                     return ((int)insertionMode).ToString(CultureInfo.InvariantCulture);\r
287             }\r
288         }\r
289 \r
290         private static Dictionary<string, object> ObjectToCaseSensitiveDictionary(object values) {\r
291             Dictionary<string, object> dict = new Dictionary<string, object>(StringComparer.Ordinal);\r
292             if (values != null) {\r
293                 foreach (PropertyDescriptor prop in TypeDescriptor.GetProperties(values)) {\r
294                     object val = prop.GetValue(values);\r
295                     dict[prop.Name] = val;\r
296                 }\r
297             }\r
298             return dict;\r
299         }\r
300 \r
301         private static string GenerateLink(string linkText, string targetUrl, AjaxOptions ajaxOptions, IDictionary<string, object> htmlAttributes) {\r
302             TagBuilder tag = new TagBuilder("a") {\r
303                 InnerHtml = HttpUtility.HtmlEncode(linkText)\r
304             };\r
305 \r
306             tag.MergeAttributes(htmlAttributes);\r
307             tag.MergeAttribute("href", targetUrl);\r
308             tag.MergeAttribute("onclick", GenerateAjaxScript(ajaxOptions, LinkOnClickFormat));\r
309 \r
310             return tag.ToString(TagRenderMode.Normal);\r
311         }\r
312 \r
313         private static string GenerateAjaxScript(AjaxOptions ajaxOptions, string scriptFormat) {\r
314             string optionsString = ajaxOptions.ToJavascriptString();\r
315             return String.Format(CultureInfo.InvariantCulture, scriptFormat, optionsString);\r
316         }\r
317 \r
318         private static AjaxOptions GetAjaxOptions(AjaxOptions ajaxOptions) {\r
319             return (ajaxOptions != null) ? ajaxOptions : new AjaxOptions();\r
320         }\r
321     }\r
322 }\r