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