2010-06-21 Marek Habersack <mhabersack@novell.com>
[mcs.git] / class / System.Web.Mvc / System.Web.Mvc / ViewUserControl.cs
blobe33501d94fed6e112cc3c2edd8219c0f44100f6c
1 /* ****************************************************************************
3 * Copyright (c) Microsoft Corporation. All rights reserved.
5 * This software is subject to the Microsoft Public License (Ms-PL).
6 * A copy of the license can be found in the license.htm file included
7 * in this distribution.
9 * You must not remove this notice, or any other, from this software.
11 * ***************************************************************************/
13 namespace System.Web.Mvc {
14 using System;
15 using System.ComponentModel;
16 using System.Diagnostics.CodeAnalysis;
17 using System.Globalization;
18 using System.Web.Mvc.Resources;
19 using System.Web.UI;
21 [FileLevelControlBuilder(typeof(ViewUserControlControlBuilder))]
22 public class ViewUserControl : UserControl, IViewDataContainer {
23 private AjaxHelper _ajaxHelper;
24 private HtmlHelper _htmlHelper;
25 private ViewContext _viewContext;
26 private ViewDataDictionary _viewData;
27 private string _viewDataKey;
29 public AjaxHelper Ajax {
30 get {
31 if (_ajaxHelper == null) {
32 _ajaxHelper = new AjaxHelper(ViewContext, this);
34 return _ajaxHelper;
38 public HtmlHelper Html {
39 get {
40 if (_htmlHelper == null) {
41 _htmlHelper = new HtmlHelper(ViewContext, this);
43 return _htmlHelper;
47 public object Model {
48 get {
49 return ViewData.Model;
53 public TempDataDictionary TempData {
54 get {
55 return ViewPage.TempData;
59 public UrlHelper Url {
60 get {
61 return ViewPage.Url;
65 [Browsable(false)]
66 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
67 public ViewContext ViewContext {
68 get {
69 return _viewContext ?? ViewPage.ViewContext;
71 set {
72 _viewContext = value;
76 [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly",
77 Justification = "This is the mechanism by which the ViewUserControl gets its ViewDataDictionary object.")]
78 [Browsable(false)]
79 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
80 public ViewDataDictionary ViewData {
81 get {
82 EnsureViewData();
83 return _viewData;
85 set {
86 SetViewData(value);
90 [DefaultValue("")]
91 public string ViewDataKey {
92 get {
93 return _viewDataKey ?? String.Empty;
95 set {
96 _viewDataKey = value;
100 internal ViewPage ViewPage {
101 get {
102 ViewPage viewPage = Page as ViewPage;
103 if (viewPage == null) {
104 throw new InvalidOperationException(MvcResources.ViewUserControl_RequiresViewPage);
106 return viewPage;
110 public HtmlTextWriter Writer {
111 get {
112 return ViewPage.Writer;
116 protected virtual void SetViewData(ViewDataDictionary viewData) {
117 _viewData = viewData;
120 protected void EnsureViewData() {
121 if (_viewData != null) {
122 return;
125 // Get the ViewData for this ViewUserControl, optionally using the specified ViewDataKey
126 IViewDataContainer vdc = GetViewDataContainer(this);
127 if (vdc == null) {
128 throw new InvalidOperationException(
129 String.Format(
130 CultureInfo.CurrentUICulture,
131 MvcResources.ViewUserControl_RequiresViewDataProvider,
132 AppRelativeVirtualPath));
135 ViewDataDictionary myViewData = vdc.ViewData;
137 // If we have a ViewDataKey, try to extract the ViewData from the dictionary, otherwise
138 // return the container's ViewData.
139 if (!String.IsNullOrEmpty(ViewDataKey)) {
140 object target = myViewData.Eval(ViewDataKey);
141 myViewData = target as ViewDataDictionary ?? new ViewDataDictionary(myViewData) { Model = target };
144 SetViewData(myViewData);
147 private static IViewDataContainer GetViewDataContainer(Control control) {
148 // Walk up the control hierarchy until we find someone that implements IViewDataContainer
149 while (control != null) {
150 control = control.Parent;
151 IViewDataContainer vdc = control as IViewDataContainer;
152 if (vdc != null) {
153 return vdc;
156 return null;
159 public virtual void RenderView(ViewContext viewContext) {
160 // TODO: Remove this hack. Without it, the browser appears to always load cached output
161 viewContext.HttpContext.Response.Cache.SetExpires(DateTime.Now);
162 ViewUserControlContainerPage containerPage = new ViewUserControlContainerPage(this);
163 // Tracing requires Page IDs to be unique.
164 ID = Guid.NewGuid().ToString();
166 RenderViewAndRestoreContentType(containerPage, viewContext);
169 internal static void RenderViewAndRestoreContentType(ViewPage containerPage, ViewContext viewContext) {
170 // We need to restore the Content-Type since Page.SetIntrinsics() will reset it. It's not possible
171 // to work around the call to SetIntrinsics() since the control's render method requires the
172 // containing page's Response property to be non-null, and SetIntrinsics() is the only way to set
173 // this.
174 string savedContentType = viewContext.HttpContext.Response.ContentType;
175 containerPage.RenderView(viewContext);
176 viewContext.HttpContext.Response.ContentType = savedContentType;
179 private sealed class ViewUserControlContainerPage : ViewPage {
180 public ViewUserControlContainerPage(ViewUserControl userControl) {
181 Controls.Add(userControl);