New test.
[mono.git] / mcs / class / System.Web.Mvc2 / System.Web.Mvc / ViewUserControl.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.ComponentModel;\r
16     using System.Diagnostics.CodeAnalysis;\r
17     using System.Globalization;\r
18     using System.IO;\r
19     using System.Web.Mvc.Resources;\r
20     using System.Web.UI;\r
21 \r
22     [FileLevelControlBuilder(typeof(ViewUserControlControlBuilder))]\r
23     public class ViewUserControl : UserControl, IViewDataContainer {\r
24         private AjaxHelper<object> _ajaxHelper;\r
25         private HtmlHelper<object> _htmlHelper;\r
26         private ViewContext _viewContext;\r
27         private ViewDataDictionary _viewData;\r
28         private string _viewDataKey;\r
29 \r
30         public AjaxHelper<object> Ajax {\r
31             get {\r
32                 if (_ajaxHelper == null) {\r
33                     _ajaxHelper = new AjaxHelper<object>(ViewContext, this);\r
34                 }\r
35                 return _ajaxHelper;\r
36             }\r
37         }\r
38 \r
39         public HtmlHelper<object> Html {\r
40             get {\r
41                 if (_htmlHelper == null) {\r
42                     _htmlHelper = new HtmlHelper<object>(ViewContext, this);\r
43                 }\r
44                 return _htmlHelper;\r
45             }\r
46         }\r
47 \r
48         public object Model {\r
49             get {\r
50                 return ViewData.Model;\r
51             }\r
52         }\r
53 \r
54         public TempDataDictionary TempData {\r
55             get {\r
56                 return ViewPage.TempData;\r
57             }\r
58         }\r
59 \r
60         public UrlHelper Url {\r
61             get {\r
62                 return ViewPage.Url;\r
63             }\r
64         }\r
65 \r
66         [Browsable(false)]\r
67         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]\r
68         public ViewContext ViewContext {\r
69             get {\r
70                 return _viewContext ?? ViewPage.ViewContext;\r
71             }\r
72             set {\r
73                 _viewContext = value;\r
74             }\r
75         }\r
76 \r
77         [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly",\r
78             Justification = "This is the mechanism by which the ViewUserControl gets its ViewDataDictionary object.")]\r
79         [Browsable(false)]\r
80         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]\r
81         public ViewDataDictionary ViewData {\r
82             get {\r
83                 EnsureViewData();\r
84                 return _viewData;\r
85             }\r
86             set {\r
87                 SetViewData(value);\r
88             }\r
89         }\r
90 \r
91         [DefaultValue("")]\r
92         public string ViewDataKey {\r
93             get {\r
94                 return _viewDataKey ?? String.Empty;\r
95             }\r
96             set {\r
97                 _viewDataKey = value;\r
98             }\r
99         }\r
100 \r
101         internal ViewPage ViewPage {\r
102             get {\r
103                 ViewPage viewPage = Page as ViewPage;\r
104                 if (viewPage == null) {\r
105                     throw new InvalidOperationException(MvcResources.ViewUserControl_RequiresViewPage);\r
106                 }\r
107                 return viewPage;\r
108             }\r
109         }\r
110 \r
111         public HtmlTextWriter Writer {\r
112             get {\r
113                 return ViewPage.Writer;\r
114             }\r
115         }\r
116 \r
117         protected virtual void SetViewData(ViewDataDictionary viewData) {\r
118             _viewData = viewData;\r
119         }\r
120 \r
121         protected void EnsureViewData() {\r
122             if (_viewData != null) {\r
123                 return;\r
124             }\r
125 \r
126             // Get the ViewData for this ViewUserControl, optionally using the specified ViewDataKey\r
127             IViewDataContainer vdc = GetViewDataContainer(this);\r
128             if (vdc == null) {\r
129                 throw new InvalidOperationException(\r
130                     String.Format(\r
131                         CultureInfo.CurrentUICulture,\r
132                         MvcResources.ViewUserControl_RequiresViewDataProvider,\r
133                         AppRelativeVirtualPath));\r
134             }\r
135 \r
136             ViewDataDictionary myViewData = vdc.ViewData;\r
137 \r
138             // If we have a ViewDataKey, try to extract the ViewData from the dictionary, otherwise\r
139             // return the container's ViewData.\r
140             if (!String.IsNullOrEmpty(ViewDataKey)) {\r
141                 object target = myViewData.Eval(ViewDataKey);\r
142                 myViewData = target as ViewDataDictionary ?? new ViewDataDictionary(myViewData) { Model = target };\r
143             }\r
144 \r
145             SetViewData(myViewData);\r
146         }\r
147 \r
148         private static IViewDataContainer GetViewDataContainer(Control control) {\r
149             // Walk up the control hierarchy until we find someone that implements IViewDataContainer\r
150             while (control != null) {\r
151                 control = control.Parent;\r
152                 IViewDataContainer vdc = control as IViewDataContainer;\r
153                 if (vdc != null) {\r
154                     return vdc;\r
155                 }\r
156             }\r
157             return null;\r
158         }\r
159 \r
160         public virtual void RenderView(ViewContext viewContext) {\r
161             ViewUserControlContainerPage containerPage = new ViewUserControlContainerPage(this);\r
162 \r
163             RenderViewAndRestoreContentType(containerPage, viewContext);\r
164         }\r
165 \r
166         internal static void RenderViewAndRestoreContentType(ViewPage containerPage, ViewContext viewContext) {\r
167             // We need to restore the Content-Type since Page.SetIntrinsics() will reset it. It's not possible\r
168             // to work around the call to SetIntrinsics() since the control's render method requires the\r
169             // containing page's Response property to be non-null, and SetIntrinsics() is the only way to set\r
170             // this.\r
171             string savedContentType = viewContext.HttpContext.Response.ContentType;\r
172             containerPage.RenderView(viewContext);\r
173             viewContext.HttpContext.Response.ContentType = savedContentType;\r
174         }\r
175 \r
176         [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "textWriter",\r
177             Justification = "This method existed in MVC 1.0 and has been deprecated.")]\r
178         [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic",\r
179             Justification = "This method existed in MVC 1.0 and has been deprecated.")]\r
180         [Obsolete("The TextWriter is now provided by the ViewContext object passed to the RenderView method.", true /* error */)]\r
181         public void SetTextWriter(TextWriter textWriter) {\r
182             // this is now a no-op\r
183         }\r
184 \r
185         private sealed class ViewUserControlContainerPage : ViewPage {\r
186             private readonly ViewUserControl _userControl;\r
187 \r
188             public ViewUserControlContainerPage(ViewUserControl userControl) {\r
189                 _userControl = userControl;\r
190             }\r
191 \r
192             public override void ProcessRequest(HttpContext context) {\r
193                 _userControl.ID = ViewPage.NextId();\r
194                 Controls.Add(_userControl);\r
195 \r
196                 base.ProcessRequest(context);\r
197             }\r
198         }\r
199     }\r
200 }\r