New tests.
[mono.git] / mcs / class / System.Web.Mvc2 / System.Web.Mvc / ViewPage.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.Diagnostics.CodeAnalysis;\r
16     using System.Globalization;\r
17     using System.IO;\r
18     using System.Text;\r
19     using System.Web;\r
20     using System.Web.UI;\r
21 \r
22     [FileLevelControlBuilder(typeof(ViewPageControlBuilder))]\r
23     public class ViewPage : Page, IViewDataContainer {\r
24 \r
25         private string _masterLocation;\r
26         [ThreadStatic]\r
27         private static int _nextId;\r
28         private ViewDataDictionary _viewData;\r
29 \r
30         public AjaxHelper<object> Ajax {\r
31             get;\r
32             set;\r
33         }\r
34 \r
35         public HtmlHelper<object> Html {\r
36             get;\r
37             set;\r
38         }\r
39 \r
40         public string MasterLocation {\r
41             get {\r
42                 return _masterLocation ?? String.Empty;\r
43             }\r
44             set {\r
45                 _masterLocation = value;\r
46             }\r
47         }\r
48 \r
49         public object Model {\r
50             get {\r
51                 return ViewData.Model;\r
52             }\r
53         }\r
54 \r
55         public TempDataDictionary TempData {\r
56             get {\r
57                 return ViewContext.TempData;\r
58             }\r
59         }\r
60 \r
61         public UrlHelper Url {\r
62             get;\r
63             set;\r
64         }\r
65 \r
66         public ViewContext ViewContext {\r
67             get;\r
68             set;\r
69         }\r
70 \r
71         [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly",\r
72             Justification = "This is the mechanism by which the ViewPage gets its ViewDataDictionary object.")]\r
73         public ViewDataDictionary ViewData {\r
74             get {\r
75                 if (_viewData == null) {\r
76                     SetViewData(new ViewDataDictionary());\r
77                 }\r
78                 return _viewData;\r
79             }\r
80             set {\r
81                 SetViewData(value);\r
82             }\r
83         }\r
84 \r
85         public HtmlTextWriter Writer {\r
86             get;\r
87             private set;\r
88         }\r
89 \r
90         public virtual void InitHelpers() {\r
91             Ajax = new AjaxHelper<object>(ViewContext, this);\r
92             Html = new HtmlHelper<object>(ViewContext, this);\r
93             Url = new UrlHelper(ViewContext.RequestContext);\r
94         }\r
95 \r
96         internal static string NextId() {\r
97             return (++_nextId).ToString(CultureInfo.InvariantCulture);\r
98         }\r
99 \r
100         [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers")]\r
101         protected override void OnPreInit(EventArgs e) {\r
102             base.OnPreInit(e);\r
103 \r
104             if (!String.IsNullOrEmpty(MasterLocation)) {\r
105                 MasterPageFile = MasterLocation;\r
106             }\r
107         }\r
108 \r
109         public override void ProcessRequest(HttpContext context) {\r
110             // Tracing requires IDs to be unique.\r
111             ID = NextId();\r
112 \r
113             base.ProcessRequest(context);\r
114         }\r
115 \r
116         protected override void Render(HtmlTextWriter writer) {\r
117             Writer = writer;\r
118             try {\r
119                 base.Render(writer);\r
120             }\r
121             finally {\r
122                 Writer = null;\r
123             }\r
124         }\r
125 \r
126         public virtual void RenderView(ViewContext viewContext) {\r
127             ViewContext = viewContext;\r
128             InitHelpers();\r
129 \r
130             bool needServerExecute = false;\r
131 \r
132             SwitchWriter switchWriter = viewContext.HttpContext.Response.Output as SwitchWriter;\r
133             if (switchWriter == null) {\r
134                 switchWriter = new SwitchWriter();\r
135                 needServerExecute = true;\r
136             }\r
137 \r
138             using (switchWriter.Scope(viewContext.Writer)) {\r
139                 if (needServerExecute) {\r
140                     // It's safe to reset the _nextId within a Server.Execute() since it pushes a new TraceContext onto\r
141                     // the stack, so there won't be an ID conflict.\r
142                     int originalNextId = _nextId;\r
143                     try {\r
144                         _nextId = 0;\r
145                         viewContext.HttpContext.Server.Execute(HttpHandlerUtil.WrapForServerExecute(this), switchWriter, true /* preserveForm */);\r
146                     }\r
147                     finally {\r
148                         // Restore the original _nextId in case this isn't actually the outermost view, since resetting\r
149                         // the _nextId may now cause trace ID conflicts in the outer view.\r
150                         _nextId = originalNextId;\r
151                     }\r
152                 }\r
153                 else {\r
154                     ProcessRequest(HttpContext.Current);\r
155                 }\r
156             }\r
157         }\r
158 \r
159         [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "textWriter",\r
160             Justification = "This method existed in MVC 1.0 and has been deprecated.")]\r
161         [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic",\r
162             Justification = "This method existed in MVC 1.0 and has been deprecated.")]\r
163         [Obsolete("The TextWriter is now provided by the ViewContext object passed to the RenderView method.", true /* error */)]\r
164         public void SetTextWriter(TextWriter textWriter) {\r
165             // this is now a no-op\r
166         }\r
167 \r
168         protected virtual void SetViewData(ViewDataDictionary viewData) {\r
169             _viewData = viewData;\r
170         }\r
171 \r
172         internal class SwitchWriter : TextWriter {\r
173             public SwitchWriter()\r
174                 : base(CultureInfo.CurrentCulture) {\r
175             }\r
176 \r
177             public override Encoding Encoding {\r
178                 get {\r
179                     return InnerWriter.Encoding;\r
180                 }\r
181             }\r
182 \r
183             public override IFormatProvider FormatProvider {\r
184                 get {\r
185                     return InnerWriter.FormatProvider;\r
186                 }\r
187             }\r
188 \r
189             internal TextWriter InnerWriter {\r
190                 get;\r
191                 set;\r
192             }\r
193 \r
194             public override string NewLine {\r
195                 get {\r
196                     return InnerWriter.NewLine;\r
197                 }\r
198                 set {\r
199                     InnerWriter.NewLine = value;\r
200                 }\r
201             }\r
202 \r
203             public override void Close() {\r
204                 InnerWriter.Close();\r
205             }\r
206 \r
207             public override void Flush() {\r
208                 InnerWriter.Flush();\r
209             }\r
210 \r
211             public IDisposable Scope(TextWriter writer) {\r
212                 WriterScope scope = new WriterScope(this, InnerWriter);\r
213 \r
214                 if (writer != this) {\r
215                     InnerWriter = writer;\r
216                 }\r
217 \r
218                 return scope;\r
219             }\r
220 \r
221             public override void Write(bool value) {\r
222                 InnerWriter.Write(value);\r
223             }\r
224 \r
225             public override void Write(char value) {\r
226                 InnerWriter.Write(value);\r
227             }\r
228 \r
229             public override void Write(char[] buffer) {\r
230                 InnerWriter.Write(buffer);\r
231             }\r
232 \r
233             public override void Write(char[] buffer, int index, int count) {\r
234                 InnerWriter.Write(buffer, index, count);\r
235             }\r
236 \r
237             public override void Write(decimal value) {\r
238                 InnerWriter.Write(value);\r
239             }\r
240 \r
241             public override void Write(double value) {\r
242                 InnerWriter.Write(value);\r
243             }\r
244 \r
245             public override void Write(float value) {\r
246                 InnerWriter.Write(value);\r
247             }\r
248 \r
249             public override void Write(int value) {\r
250                 InnerWriter.Write(value);\r
251             }\r
252 \r
253             public override void Write(long value) {\r
254                 InnerWriter.Write(value);\r
255             }\r
256 \r
257             public override void Write(object value) {\r
258                 InnerWriter.Write(value);\r
259             }\r
260 \r
261             public override void Write(string format, object arg0) {\r
262                 InnerWriter.Write(format, arg0);\r
263             }\r
264 \r
265             public override void Write(string format, object arg0, object arg1) {\r
266                 InnerWriter.Write(format, arg0, arg1);\r
267             }\r
268 \r
269             public override void Write(string format, object arg0, object arg1, object arg2) {\r
270                 InnerWriter.Write(format, arg0, arg1, arg2);\r
271             }\r
272 \r
273             public override void Write(string format, params object[] arg) {\r
274                 InnerWriter.Write(format, arg);\r
275             }\r
276 \r
277             public override void Write(string value) {\r
278                 InnerWriter.Write(value);\r
279             }\r
280 \r
281             public override void Write(uint value) {\r
282                 InnerWriter.Write(value);\r
283             }\r
284 \r
285             public override void Write(ulong value) {\r
286                 InnerWriter.Write(value);\r
287             }\r
288 \r
289             public override void WriteLine() {\r
290                 InnerWriter.WriteLine();\r
291             }\r
292 \r
293             public override void WriteLine(bool value) {\r
294                 InnerWriter.WriteLine(value);\r
295             }\r
296 \r
297             public override void WriteLine(char value) {\r
298                 InnerWriter.WriteLine(value);\r
299             }\r
300 \r
301             public override void WriteLine(char[] buffer) {\r
302                 InnerWriter.WriteLine(buffer);\r
303             }\r
304 \r
305             public override void WriteLine(char[] buffer, int index, int count) {\r
306                 InnerWriter.WriteLine(buffer, index, count);\r
307             }\r
308 \r
309             public override void WriteLine(decimal value) {\r
310                 InnerWriter.WriteLine(value);\r
311             }\r
312 \r
313             public override void WriteLine(double value) {\r
314                 InnerWriter.WriteLine(value);\r
315             }\r
316 \r
317             public override void WriteLine(float value) {\r
318                 InnerWriter.WriteLine(value);\r
319             }\r
320 \r
321             public override void WriteLine(int value) {\r
322                 InnerWriter.WriteLine(value);\r
323             }\r
324 \r
325             public override void WriteLine(long value) {\r
326                 InnerWriter.WriteLine(value);\r
327             }\r
328 \r
329             public override void WriteLine(object value) {\r
330                 InnerWriter.WriteLine(value);\r
331             }\r
332 \r
333             public override void WriteLine(string format, object arg0) {\r
334                 InnerWriter.WriteLine(format, arg0);\r
335             }\r
336 \r
337             public override void WriteLine(string format, object arg0, object arg1) {\r
338                 InnerWriter.WriteLine(format, arg0, arg1);\r
339             }\r
340 \r
341             public override void WriteLine(string format, object arg0, object arg1, object arg2) {\r
342                 InnerWriter.WriteLine(format, arg0, arg1, arg2);\r
343             }\r
344 \r
345             public override void WriteLine(string format, params object[] arg) {\r
346                 InnerWriter.WriteLine(format, arg);\r
347             }\r
348 \r
349             public override void WriteLine(string value) {\r
350                 InnerWriter.WriteLine(value);\r
351             }\r
352 \r
353             public override void WriteLine(uint value) {\r
354                 InnerWriter.WriteLine(value);\r
355             }\r
356 \r
357             public override void WriteLine(ulong value) {\r
358                 InnerWriter.WriteLine(value);\r
359             }\r
360 \r
361             private sealed class WriterScope : IDisposable {\r
362                 private SwitchWriter _switchWriter;\r
363                 private TextWriter _writerToRestore;\r
364 \r
365                 public WriterScope(SwitchWriter switchWriter, TextWriter writerToRestore) {\r
366                     _switchWriter = switchWriter;\r
367                     _writerToRestore = writerToRestore;\r
368                 }\r
369 \r
370                 public void Dispose() {\r
371                     _switchWriter.InnerWriter = _writerToRestore;\r
372                 }\r
373             }\r
374 \r
375         }\r
376 \r
377     }\r
378 }\r